Sfoglia il codice sorgente

add binary primitives

Ugochukwu Mmaduekwe 2 settimane fa
parent
commit
71dfa0bdad

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

@@ -59,7 +59,6 @@ uses
   ClpCipherUtilities in '..\..\CryptoLib\src\Crypto\Ciphers\ClpCipherUtilities.pas',
   ClpCollectionUtilities in '..\..\CryptoLib\src\GeneralUtilities\ClpCollectionUtilities.pas',
   ClpConverters in '..\..\CryptoLib\src\GeneralUtilities\ClpConverters.pas',
-  ClpBitUtilities in '..\..\CryptoLib\src\GeneralUtilities\ClpBitUtilities.pas',
   ClpCryptLibObjectIdentifiers in '..\..\CryptoLib\src\Asn1\CryptLib\ClpCryptLibObjectIdentifiers.pas',
   ClpCryptoApiRandomGenerator in '..\..\CryptoLib\src\Rngs\ClpCryptoApiRandomGenerator.pas',
   ClpCryptoLibComparers in '..\..\CryptoLib\src\GeneralUtilities\ClpCryptoLibComparers.pas',
@@ -513,6 +512,9 @@ uses
   ClpIX509RsaAsn1Objects in '..\..\CryptoLib\src\Interfaces\Asn1\X509\ClpIX509RsaAsn1Objects.pas',
   ClpX509DsaAsn1Objects in '..\..\CryptoLib\src\Asn1\X509\ClpX509DsaAsn1Objects.pas',
   ClpX509RsaAsn1Objects in '..\..\CryptoLib\src\Asn1\X509\ClpX509RsaAsn1Objects.pas',
+  ClpBinaryPrimitives in '..\..\CryptoLib\src\BitUtilities\ClpBinaryPrimitives.pas',
+  ClpBitUtilities in '..\..\CryptoLib\src\BitUtilities\ClpBitUtilities.pas',
+  ClpPack in '..\..\CryptoLib\src\BitUtilities\ClpPack.pas',
   ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
   ClpIFixedSecureRandom in '..\src\Utils\ClpIFixedSecureRandom.pas',
   ClpIShortenedDigest in '..\src\Utils\ClpIShortenedDigest.pas',

+ 454 - 0
CryptoLib/src/BitUtilities/ClpBinaryPrimitives.pas

@@ -0,0 +1,454 @@
+{ *********************************************************************************** }
+{ *                              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 ClpBinaryPrimitives;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes;
+
+type
+  TBinaryPrimitives = class
+  private
+    class procedure CheckBounds(const AData: TCryptoLibByteArray; AOffset, ANeeded: Integer); static; inline;
+
+    // UInt16 helpers
+    class procedure WriteUInt16LEInternal(AValue: UInt16; const AData: TCryptoLibByteArray; AOffset: Integer); static; inline;
+    class procedure WriteUInt16BEInternal(AValue: UInt16; const AData: TCryptoLibByteArray; AOffset: Integer); static; inline;
+    class function ReadUInt16LEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16; static; inline;
+    class function ReadUInt16BEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16; static; inline;
+
+    // UInt32 helpers
+    class procedure WriteUInt32LEInternal(AValue: UInt32; const AData: TCryptoLibByteArray; AOffset: Integer); static; inline;
+    class procedure WriteUInt32BEInternal(AValue: UInt32; const AData: TCryptoLibByteArray; AOffset: Integer); static; inline;
+    class function ReadUInt32LEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32; static; inline;
+    class function ReadUInt32BEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32; static; inline;
+
+    // UInt64 helpers
+    class procedure WriteUInt64LEInternal(AValue: UInt64; const AData: TCryptoLibByteArray; AOffset: Integer); static; inline;
+    class procedure WriteUInt64BEInternal(AValue: UInt64; const AData: TCryptoLibByteArray; AOffset: Integer); static; inline;
+    class function ReadUInt64LEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64; static; inline;
+    class function ReadUInt64BEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64; static; inline;
+
+  public
+    class procedure WriteUInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt16); static;
+    class procedure WriteUInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt32); static;
+    class procedure WriteUInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt64); static;
+
+    class procedure WriteInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int16); static;
+    class procedure WriteInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int32); static;
+    class procedure WriteInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int64); static;
+
+    class procedure WriteSingleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Single); static;
+    class procedure WriteDoubleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Double); static;
+
+    class procedure WriteUInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt16); static;
+    class procedure WriteUInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt32); static;
+    class procedure WriteUInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt64); static;
+
+    class procedure WriteInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int16); static;
+    class procedure WriteInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int32); static;
+    class procedure WriteInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int64); static;
+
+    class procedure WriteSingleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Single); static;
+    class procedure WriteDoubleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Double); static;
+
+    class function ReadUInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16; static;
+    class function ReadUInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32; static;
+    class function ReadUInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64; static;
+
+    class function ReadInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int16; static;
+    class function ReadInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int32; static;
+    class function ReadInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int64; static;
+
+    class function ReadSingleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Single; static;
+    class function ReadDoubleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Double; static;
+
+    class function ReadUInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16; static;
+    class function ReadUInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32; static;
+    class function ReadUInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64; static;
+
+    class function ReadInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int16; static;
+    class function ReadInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int32; static;
+    class function ReadInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int64; static;
+
+    class function ReadSingleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Single; static;
+    class function ReadDoubleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Double; static;
+  end;
+
+implementation
+
+{ TBinaryPrimitives }
+
+class procedure TBinaryPrimitives.CheckBounds(const AData: TCryptoLibByteArray; AOffset, ANeeded: Integer);
+begin
+  if (AOffset < 0) or (AOffset + ANeeded > Length(AData)) then
+    raise EArgumentOutOfRangeException.Create('AOffset');
+end;
+
+// ============================================================================
+// UInt16 Internal Helpers
+// ============================================================================
+
+class procedure TBinaryPrimitives.WriteUInt16LEInternal(AValue: UInt16; const AData: TCryptoLibByteArray; AOffset: Integer);
+begin
+  AData[AOffset]     := Byte(AValue);
+  AData[AOffset + 1] := Byte(AValue shr 8);
+end;
+
+class procedure TBinaryPrimitives.WriteUInt16BEInternal(AValue: UInt16; const AData: TCryptoLibByteArray; AOffset: Integer);
+begin
+  AData[AOffset]     := Byte(AValue shr 8);
+  AData[AOffset + 1] := Byte(AValue);
+end;
+
+class function TBinaryPrimitives.ReadUInt16LEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16;
+begin
+  Result := UInt16(AData[AOffset]) or (UInt16(AData[AOffset + 1]) shl 8);
+end;
+
+class function TBinaryPrimitives.ReadUInt16BEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16;
+begin
+  Result := (UInt16(AData[AOffset]) shl 8) or UInt16(AData[AOffset + 1]);
+end;
+
+// ============================================================================
+// UInt32 Internal Helpers
+// ============================================================================
+
+class procedure TBinaryPrimitives.WriteUInt32LEInternal(AValue: UInt32; const AData: TCryptoLibByteArray; AOffset: Integer);
+begin
+  AData[AOffset]     := Byte(AValue);
+  AData[AOffset + 1] := Byte(AValue shr 8);
+  AData[AOffset + 2] := Byte(AValue shr 16);
+  AData[AOffset + 3] := Byte(AValue shr 24);
+end;
+
+class procedure TBinaryPrimitives.WriteUInt32BEInternal(AValue: UInt32; const AData: TCryptoLibByteArray; AOffset: Integer);
+begin
+  AData[AOffset]     := Byte(AValue shr 24);
+  AData[AOffset + 1] := Byte(AValue shr 16);
+  AData[AOffset + 2] := Byte(AValue shr 8);
+  AData[AOffset + 3] := Byte(AValue);
+end;
+
+class function TBinaryPrimitives.ReadUInt32LEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32;
+begin
+  Result := UInt32(AData[AOffset]) or
+            (UInt32(AData[AOffset + 1]) shl 8) or
+            (UInt32(AData[AOffset + 2]) shl 16) or
+            (UInt32(AData[AOffset + 3]) shl 24);
+end;
+
+class function TBinaryPrimitives.ReadUInt32BEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32;
+begin
+  Result := (UInt32(AData[AOffset]) shl 24) or
+            (UInt32(AData[AOffset + 1]) shl 16) or
+            (UInt32(AData[AOffset + 2]) shl 8) or
+            UInt32(AData[AOffset + 3]);
+end;
+
+// ============================================================================
+// UInt64 Internal Helpers
+// ============================================================================
+
+class procedure TBinaryPrimitives.WriteUInt64LEInternal(AValue: UInt64; const AData: TCryptoLibByteArray; AOffset: Integer);
+begin
+  AData[AOffset]     := Byte(AValue);
+  AData[AOffset + 1] := Byte(AValue shr 8);
+  AData[AOffset + 2] := Byte(AValue shr 16);
+  AData[AOffset + 3] := Byte(AValue shr 24);
+  AData[AOffset + 4] := Byte(AValue shr 32);
+  AData[AOffset + 5] := Byte(AValue shr 40);
+  AData[AOffset + 6] := Byte(AValue shr 48);
+  AData[AOffset + 7] := Byte(AValue shr 56);
+end;
+
+class procedure TBinaryPrimitives.WriteUInt64BEInternal(AValue: UInt64; const AData: TCryptoLibByteArray; AOffset: Integer);
+begin
+  AData[AOffset]     := Byte(AValue shr 56);
+  AData[AOffset + 1] := Byte(AValue shr 48);
+  AData[AOffset + 2] := Byte(AValue shr 40);
+  AData[AOffset + 3] := Byte(AValue shr 32);
+  AData[AOffset + 4] := Byte(AValue shr 24);
+  AData[AOffset + 5] := Byte(AValue shr 16);
+  AData[AOffset + 6] := Byte(AValue shr 8);
+  AData[AOffset + 7] := Byte(AValue);
+end;
+
+class function TBinaryPrimitives.ReadUInt64LEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64;
+begin
+  Result := UInt64(AData[AOffset]) or
+            (UInt64(AData[AOffset + 1]) shl 8) or
+            (UInt64(AData[AOffset + 2]) shl 16) or
+            (UInt64(AData[AOffset + 3]) shl 24) or
+            (UInt64(AData[AOffset + 4]) shl 32) or
+            (UInt64(AData[AOffset + 5]) shl 40) or
+            (UInt64(AData[AOffset + 6]) shl 48) or
+            (UInt64(AData[AOffset + 7]) shl 56);
+end;
+
+class function TBinaryPrimitives.ReadUInt64BEInternal(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64;
+begin
+  Result := (UInt64(AData[AOffset]) shl 56) or
+            (UInt64(AData[AOffset + 1]) shl 48) or
+            (UInt64(AData[AOffset + 2]) shl 40) or
+            (UInt64(AData[AOffset + 3]) shl 32) or
+            (UInt64(AData[AOffset + 4]) shl 24) or
+            (UInt64(AData[AOffset + 5]) shl 16) or
+            (UInt64(AData[AOffset + 6]) shl 8) or
+            UInt64(AData[AOffset + 7]);
+end;
+
+// ============================================================================
+// Public Write Methods - Little Endian
+// ============================================================================
+
+class procedure TBinaryPrimitives.WriteUInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt16);
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt16));
+  WriteUInt16LEInternal(AValue, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteUInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt32);
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt32));
+  WriteUInt32LEInternal(AValue, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteUInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt64);
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt64));
+  WriteUInt64LEInternal(AValue, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int16);
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int16));
+  WriteUInt16LEInternal(UInt16(AValue), AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int32);
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int32));
+  WriteUInt32LEInternal(UInt32(AValue), AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int64);
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int64));
+  WriteUInt64LEInternal(UInt64(AValue), AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteSingleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Single);
+var
+  bits: UInt32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Single));
+  Move(AValue, bits, SizeOf(Single));
+  WriteUInt32LEInternal(bits, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteDoubleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Double);
+var
+  bits: UInt64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Double));
+  Move(AValue, bits, SizeOf(Double));
+  WriteUInt64LEInternal(bits, AData, AOffset);
+end;
+
+// ============================================================================
+// Public Write Methods - Big Endian
+// ============================================================================
+
+class procedure TBinaryPrimitives.WriteUInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt16);
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt16));
+  WriteUInt16BEInternal(AValue, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteUInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt32);
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt32));
+  WriteUInt32BEInternal(AValue, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteUInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: UInt64);
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt64));
+  WriteUInt64BEInternal(AValue, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int16);
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int16));
+  WriteUInt16BEInternal(UInt16(AValue), AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int32);
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int32));
+  WriteUInt32BEInternal(UInt32(AValue), AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Int64);
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int64));
+  WriteUInt64BEInternal(UInt64(AValue), AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteSingleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Single);
+var
+  bits: UInt32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Single));
+  Move(AValue, bits, SizeOf(Single));
+  WriteUInt32BEInternal(bits, AData, AOffset);
+end;
+
+class procedure TBinaryPrimitives.WriteDoubleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer; AValue: Double);
+var
+  bits: UInt64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Double));
+  Move(AValue, bits, SizeOf(Double));
+  WriteUInt64BEInternal(bits, AData, AOffset);
+end;
+
+// ============================================================================
+// Public Read Methods - Little Endian
+// ============================================================================
+
+class function TBinaryPrimitives.ReadUInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16;
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt16));
+  Result := ReadUInt16LEInternal(AData, AOffset);
+end;
+
+class function TBinaryPrimitives.ReadUInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt32));
+  Result := ReadUInt32LEInternal(AData, AOffset);
+end;
+
+class function TBinaryPrimitives.ReadUInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt64));
+  Result := ReadUInt64LEInternal(AData, AOffset);
+end;
+
+class function TBinaryPrimitives.ReadInt16LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int16;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int16));
+  Result := Int16(ReadUInt16LEInternal(AData, AOffset));
+end;
+
+class function TBinaryPrimitives.ReadInt32LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int32));
+  Result := Int32(ReadUInt32LEInternal(AData, AOffset));
+end;
+
+class function TBinaryPrimitives.ReadInt64LittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int64));
+  Result := Int64(ReadUInt64LEInternal(AData, AOffset));
+end;
+
+class function TBinaryPrimitives.ReadSingleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Single;
+var
+  bits: UInt32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Single));
+  bits := ReadUInt32LEInternal(AData, AOffset);
+  Move(bits, Result, SizeOf(Single));
+end;
+
+class function TBinaryPrimitives.ReadDoubleLittleEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Double;
+var
+  bits: UInt64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Double));
+  bits := ReadUInt64LEInternal(AData, AOffset);
+  Move(bits, Result, SizeOf(Double));
+end;
+
+// ============================================================================
+// Public Read Methods - Big Endian
+// ============================================================================
+
+class function TBinaryPrimitives.ReadUInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt16;
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt16));
+  Result := ReadUInt16BEInternal(AData, AOffset);
+end;
+
+class function TBinaryPrimitives.ReadUInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt32));
+  Result := ReadUInt32BEInternal(AData, AOffset);
+end;
+
+class function TBinaryPrimitives.ReadUInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): UInt64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(UInt64));
+  Result := ReadUInt64BEInternal(AData, AOffset);
+end;
+
+class function TBinaryPrimitives.ReadInt16BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int16;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int16));
+  Result := Int16(ReadUInt16BEInternal(AData, AOffset));
+end;
+
+class function TBinaryPrimitives.ReadInt32BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int32));
+  Result := Int32(ReadUInt32BEInternal(AData, AOffset));
+end;
+
+class function TBinaryPrimitives.ReadInt64BigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Int64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Int64));
+  Result := Int64(ReadUInt64BEInternal(AData, AOffset));
+end;
+
+class function TBinaryPrimitives.ReadSingleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Single;
+var
+  bits: UInt32;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Single));
+  bits := ReadUInt32BEInternal(AData, AOffset);
+  Move(bits, Result, SizeOf(Single));
+end;
+
+class function TBinaryPrimitives.ReadDoubleBigEndian(const AData: TCryptoLibByteArray; AOffset: Integer): Double;
+var
+  bits: UInt64;
+begin
+  CheckBounds(AData, AOffset, SizeOf(Double));
+  bits := ReadUInt64BEInternal(AData, AOffset);
+  Move(bits, Result, SizeOf(Double));
+end;
+
+end.
+

+ 0 - 0
CryptoLib/src/GeneralUtilities/ClpBitUtilities.pas → CryptoLib/src/BitUtilities/ClpBitUtilities.pas


+ 1126 - 0
CryptoLib/src/BitUtilities/ClpPack.pas

@@ -0,0 +1,1126 @@
+{ *********************************************************************************** }
+{ *                              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 ClpPack;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBinaryPrimitives,
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// Endian Conversion Utilities.
+  /// </summary>
+  TPack = class sealed
+  public
+    class procedure UInt16_To_BE(AN: UInt16; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt16_To_BE(AN: UInt16; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt16_To_BE(const ANs: TCryptoLibUInt16Array; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt16_To_BE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32;
+      const ABs: TCryptoLibByteArray; ABsOff: Int32); overload; static;
+    class function UInt16_To_BE(AN: UInt16): TCryptoLibByteArray; overload; static;
+    class function UInt16_To_BE(const ANs: TCryptoLibUInt16Array): TCryptoLibByteArray; overload; static;
+    class function UInt16_To_BE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray; overload; static;
+
+    class function BE_To_UInt16(const ABs: TCryptoLibByteArray): UInt16; overload; static;
+    class function BE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32): UInt16; overload; static;
+    class procedure BE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array; ANsOff: Int32); overload; static;
+    class procedure BE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt16Array); overload; static;
+    class procedure BE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array;
+      ANsOff: Int32; ANsLen: Int32); overload; static;
+    class function BE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt16Array; overload; static;
+
+    class procedure UInt24_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt24_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class function BE_To_UInt24(const ABs: TCryptoLibByteArray): UInt32; overload; static;
+    class function BE_To_UInt24(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32; overload; static;
+
+    class procedure UInt32_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt32_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt32_To_BE(const ANs: TCryptoLibUInt32Array; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt32_To_BE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32;
+      const ABs: TCryptoLibByteArray; ABsOff: Int32); overload; static;
+    class function UInt32_To_BE(AN: UInt32): TCryptoLibByteArray; overload; static;
+    class function UInt32_To_BE(const ANs: TCryptoLibUInt32Array): TCryptoLibByteArray; overload; static;
+    class function UInt32_To_BE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray; overload; static;
+
+    class procedure UInt32_To_BE_High(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+    class procedure UInt32_To_BE_Low(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+
+    class function BE_To_UInt32(const ABs: TCryptoLibByteArray): UInt32; overload; static;
+    class function BE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32; overload; static;
+    class procedure BE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt32Array); overload; static;
+    class procedure BE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array; ANsOff: Int32); overload; static;
+    class procedure BE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array;
+      ANsOff: Int32; ANsLen: Int32); overload; static;
+    class function BE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt32Array; overload; static;
+
+    class function BE_To_UInt32_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32; static;
+    class function BE_To_UInt32_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32; static;
+
+    class procedure UInt64_To_BE(AN: UInt64; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt64_To_BE(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt64_To_BE(const ANs: TCryptoLibUInt64Array; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt64_To_BE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32;
+      const ABs: TCryptoLibByteArray; ABsOff: Int32); overload; static;
+    class function UInt64_To_BE(AN: UInt64): TCryptoLibByteArray; overload; static;
+    class function UInt64_To_BE(const ANs: TCryptoLibUInt64Array): TCryptoLibByteArray; overload; static;
+    class function UInt64_To_BE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray; overload; static;
+
+    class procedure UInt64_To_BE_High(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+    class procedure UInt64_To_BE_Low(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+
+    class function BE_To_UInt64(const ABs: TCryptoLibByteArray): UInt64; overload; static;
+    class function BE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32): UInt64; overload; static;
+    class procedure BE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt64Array); overload; static;
+    class procedure BE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array; ANsOff: Int32); overload; static;
+    class procedure BE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array;
+      ANsOff: Int32; ANsLen: Int32); overload; static;
+    class function BE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt64Array; overload; static;
+
+    class function BE_To_UInt64_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64; static;
+    class function BE_To_UInt64_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64; static;
+
+    // Little-endian variants
+    class procedure UInt16_To_LE(AN: UInt16; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt16_To_LE(AN: UInt16; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt16_To_LE(const ANs: TCryptoLibUInt16Array; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt16_To_LE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32;
+      const ABs: TCryptoLibByteArray; ABsOff: Int32); overload; static;
+    class function UInt16_To_LE(AN: UInt16): TCryptoLibByteArray; overload; static;
+    class function UInt16_To_LE(const ANs: TCryptoLibUInt16Array): TCryptoLibByteArray; overload; static;
+    class function UInt16_To_LE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray; overload; static;
+
+    class function LE_To_UInt16(const ABs: TCryptoLibByteArray): UInt16; overload; static;
+    class function LE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32): UInt16; overload; static;
+    class procedure LE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array; ANsOff: Int32); overload; static;
+    class procedure LE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt16Array); overload; static;
+    class procedure LE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array;
+      ANsOff: Int32; ANsLen: Int32); overload; static;
+    class function LE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt16Array; overload; static;
+
+    class procedure UInt24_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt24_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class function LE_To_UInt24(const ABs: TCryptoLibByteArray): UInt32; overload; static;
+    class function LE_To_UInt24(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32; overload; static;
+
+    class procedure UInt32_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt32_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt32_To_LE(const ANs: TCryptoLibUInt32Array; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt32_To_LE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32;
+      const ABs: TCryptoLibByteArray; ABsOff: Int32); overload; static;
+    class function UInt32_To_LE(AN: UInt32): TCryptoLibByteArray; overload; static;
+    class function UInt32_To_LE(const ANs: TCryptoLibUInt32Array): TCryptoLibByteArray; overload; static;
+    class function UInt32_To_LE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray; overload; static;
+
+    class procedure UInt32_To_LE_High(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+    class procedure UInt32_To_LE_Low(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+
+    class function LE_To_UInt32(const ABs: TCryptoLibByteArray): UInt32; overload; static;
+    class function LE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32; overload; static;
+    class procedure LE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt32Array); overload; static;
+    class procedure LE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array; ANsOff: Int32); overload; static;
+    class procedure LE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array;
+      ANsOff: Int32; ANsLen: Int32); overload; static;
+    class function LE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt32Array; overload; static;
+
+    class function LE_To_UInt32_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32; static;
+    class function LE_To_UInt32_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32; static;
+
+    class procedure UInt64_To_LE(AN: UInt64; const ABs: TCryptoLibByteArray); overload; static;
+    class procedure UInt64_To_LE(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt64_To_LE(const ANs: TCryptoLibUInt64Array; const ABs: TCryptoLibByteArray; AOff: Int32); overload; static;
+    class procedure UInt64_To_LE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32;
+      const ABs: TCryptoLibByteArray; ABsOff: Int32); overload; static;
+    class function UInt64_To_LE(AN: UInt64): TCryptoLibByteArray; overload; static;
+    class function UInt64_To_LE(const ANs: TCryptoLibUInt64Array): TCryptoLibByteArray; overload; static;
+    class function UInt64_To_LE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray; overload; static;
+
+    class procedure UInt64_To_LE_High(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+    class procedure UInt64_To_LE_Low(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32); static;
+
+    class function LE_To_UInt64(const ABs: TCryptoLibByteArray): UInt64; overload; static;
+    class function LE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32): UInt64; overload; static;
+    class procedure LE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt64Array); overload; static;
+    class procedure LE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array; ANsOff: Int32); overload; static;
+    class procedure LE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array;
+      ANsOff: Int32; ANsLen: Int32); overload; static;
+    class function LE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt64Array; overload; static;
+
+    class function LE_To_UInt64_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64; static;
+    class function LE_To_UInt64_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64; static;
+  end;
+
+implementation
+
+{ TPack }
+
+class procedure TPack.UInt16_To_BE(AN: UInt16; const ABs: TCryptoLibByteArray);
+begin
+  TBinaryPrimitives.WriteUInt16BigEndian(ABs, 0, AN);
+  //ABs[0] := Byte(AN shr 8);
+  //ABs[1] := Byte(AN);
+end;
+
+class procedure TPack.UInt16_To_BE(AN: UInt16; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  TBinaryPrimitives.WriteUInt16BigEndian(ABs, AOff, AN);
+  //ABs[AOff] := Byte(AN shr 8);
+  //ABs[AOff + 1] := Byte(AN);
+end;
+
+class procedure TPack.UInt16_To_BE(const ANs: TCryptoLibUInt16Array; const ABs: TCryptoLibByteArray; AOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to System.Length(ANs) - 1 do
+  begin
+    UInt16_To_BE(ANs[LI], ABs, AOff);
+    System.Inc(AOff, 2);
+  end;
+end;
+
+class procedure TPack.UInt16_To_BE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32;
+  const ABs: TCryptoLibByteArray; ABsOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    UInt16_To_BE(ANs[ANsOff + LI], ABs, ABsOff);
+    System.Inc(ABsOff, 2);
+  end;
+end;
+
+class function TPack.UInt16_To_BE(AN: UInt16): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 2);
+  UInt16_To_BE(AN, LBs);
+  Result := LBs;
+end;
+
+class function TPack.UInt16_To_BE(const ANs: TCryptoLibUInt16Array): TCryptoLibByteArray;
+begin
+  Result := UInt16_To_BE(ANs, 0, System.Length(ANs));
+end;
+
+class function TPack.UInt16_To_BE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 2 * ANsLen);
+  UInt16_To_BE(ANs, ANsOff, ANsLen, LBs, 0);
+  Result := LBs;
+end;
+
+class function TPack.BE_To_UInt16(const ABs: TCryptoLibByteArray): UInt16;
+begin
+  Result := TBinaryPrimitives.ReadUInt16BigEndian(ABs, 0);
+  //Result := BE_To_UInt16(ABs, 0);
+end;
+
+class function TPack.BE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32): UInt16;
+begin
+  Result := TBinaryPrimitives.ReadUInt16BigEndian(ABs, AOff);
+  //Result := (UInt16(ABs[AOff]) shl 8) or UInt16(ABs[AOff + 1]);
+end;
+
+class procedure TPack.BE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array; ANsOff: Int32);
+begin
+  ANs[ANsOff] := BE_To_UInt16(ABs, ABsOff);
+end;
+
+class procedure TPack.BE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt16Array);
+begin
+  BE_To_UInt16(ABs, AOff, ANs, 0, System.Length(ANs));
+end;
+
+class procedure TPack.BE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    ANs[ANsOff + LI] := BE_To_UInt16(ABs, ABsOff);
+    System.Inc(ABsOff, 2);
+  end;
+end;
+
+class function TPack.BE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt16Array;
+var
+  LNs: TCryptoLibUInt16Array;
+begin
+  System.SetLength(LNs, ACount);
+  BE_To_UInt16(ABs, AOff, LNs);
+  Result := LNs;
+end;
+
+class procedure TPack.UInt24_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray);
+begin
+  ABs[0] := Byte(AN shr 16);
+  ABs[1] := Byte(AN shr 8);
+  ABs[2] := Byte(AN);
+end;
+
+class procedure TPack.UInt24_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  ABs[AOff] := Byte(AN shr 16);
+  ABs[AOff + 1] := Byte(AN shr 8);
+  ABs[AOff + 2] := Byte(AN);
+end;
+
+class function TPack.BE_To_UInt24(const ABs: TCryptoLibByteArray): UInt32;
+begin
+  Result := BE_To_UInt24(ABs, 0);
+end;
+
+class function TPack.BE_To_UInt24(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32;
+begin
+  Result := (UInt32(ABs[AOff]) shl 16) or (UInt32(ABs[AOff + 1]) shl 8) or UInt32(ABs[AOff + 2]);
+end;
+
+class procedure TPack.UInt32_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray);
+begin
+  TBinaryPrimitives.WriteUInt32BigEndian(ABs, 0, AN);
+  //UInt32_To_BE(AN, ABs, 0);
+end;
+
+class procedure TPack.UInt32_To_BE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  TBinaryPrimitives.WriteUInt32BigEndian(ABs, AOff, AN);
+  //ABs[AOff] := Byte(AN shr 24);
+  //ABs[AOff + 1] := Byte(AN shr 16);
+  //ABs[AOff + 2] := Byte(AN shr 8);
+  //ABs[AOff + 3] := Byte(AN);
+end;
+
+class procedure TPack.UInt32_To_BE(const ANs: TCryptoLibUInt32Array; const ABs: TCryptoLibByteArray; AOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to System.Length(ANs) - 1 do
+  begin
+    UInt32_To_BE(ANs[LI], ABs, AOff);
+    System.Inc(AOff, 4);
+  end;
+end;
+
+class procedure TPack.UInt32_To_BE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32;
+  const ABs: TCryptoLibByteArray; ABsOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    UInt32_To_BE(ANs[ANsOff + LI], ABs, ABsOff);
+    System.Inc(ABsOff, 4);
+  end;
+end;
+
+class function TPack.UInt32_To_BE(AN: UInt32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 4);
+  UInt32_To_BE(AN, LBs);
+  Result := LBs;
+end;
+
+class function TPack.UInt32_To_BE(const ANs: TCryptoLibUInt32Array): TCryptoLibByteArray;
+begin
+  Result := UInt32_To_BE(ANs, 0, System.Length(ANs));
+end;
+
+class function TPack.UInt32_To_BE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 4 * ANsLen);
+  UInt32_To_BE(ANs, ANsOff, ANsLen, LBs, 0);
+  Result := LBs;
+end;
+
+class procedure TPack.UInt32_To_BE_High(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 4 - ALen;
+  while LPos < 4 do
+  begin
+    ABs[AOff] := Byte(AN shr ((3 - LPos) * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class procedure TPack.UInt32_To_BE_Low(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    ABs[AOff] := Byte(AN shr ((ALen - 1 - LPos) * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class function TPack.BE_To_UInt32(const ABs: TCryptoLibByteArray): UInt32;
+begin
+  Result := TBinaryPrimitives.ReadUInt32BigEndian(ABs, 0);
+  //Result := BE_To_UInt32(ABs, 0);
+end;
+
+class function TPack.BE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32;
+begin
+  Result := TBinaryPrimitives.ReadUInt32BigEndian(ABs, AOff);
+  //Result := (UInt32(ABs[AOff]) shl 24) or (UInt32(ABs[AOff + 1]) shl 16) or
+  //          (UInt32(ABs[AOff + 2]) shl 8) or UInt32(ABs[AOff + 3]);
+end;
+
+class procedure TPack.BE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt32Array);
+begin
+  BE_To_UInt32(ABs, AOff, ANs, 0, System.Length(ANs));
+end;
+
+class procedure TPack.BE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array; ANsOff: Int32);
+begin
+  ANs[ANsOff] := BE_To_UInt32(ABs, ABsOff);
+end;
+
+class procedure TPack.BE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array;
+  ANsOff: Int32; ANsLen: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    ANs[ANsOff + LI] := BE_To_UInt32(ABs, ABsOff);
+    System.Inc(ABsOff, 4);
+  end;
+end;
+
+class function TPack.BE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt32Array;
+var
+  LNs: TCryptoLibUInt32Array;
+begin
+  System.SetLength(LNs, ACount);
+  BE_To_UInt32(ABs, AOff, LNs);
+  Result := LNs;
+end;
+
+class function TPack.BE_To_UInt32_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32;
+var
+  LResult: UInt32;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := (LResult shl 8) or UInt32(ABs[AOff + LPos]);
+    System.Inc(LPos);
+  end;
+
+  Result := LResult shl ((4 - ALen) * 8);
+end;
+
+class function TPack.BE_To_UInt32_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32;
+var
+  LResult: UInt32;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := (LResult shl 8) or UInt32(ABs[AOff + LPos]);
+    System.Inc(LPos);
+  end;
+
+  Result := LResult;
+end;
+
+class procedure TPack.UInt64_To_BE(AN: UInt64; const ABs: TCryptoLibByteArray);
+begin
+  TBinaryPrimitives.WriteUInt64BigEndian(ABs, 0, AN);
+  //UInt64_To_BE(AN, ABs, 0);
+end;
+
+class procedure TPack.UInt64_To_BE(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  TBinaryPrimitives.WriteUInt64BigEndian(ABs, AOff, AN);
+  //UInt32_To_BE(UInt32(AN shr 32), ABs, AOff);
+  //UInt32_To_BE(UInt32(AN), ABs, AOff + 4);
+end;
+
+class procedure TPack.UInt64_To_BE(const ANs: TCryptoLibUInt64Array; const ABs: TCryptoLibByteArray; AOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to System.Length(ANs) - 1 do
+  begin
+    UInt64_To_BE(ANs[LI], ABs, AOff);
+    System.Inc(AOff, 8);
+  end;
+end;
+
+class procedure TPack.UInt64_To_BE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32;
+  const ABs: TCryptoLibByteArray; ABsOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    UInt64_To_BE(ANs[ANsOff + LI], ABs, ABsOff);
+    System.Inc(ABsOff, 8);
+  end;
+end;
+
+class function TPack.UInt64_To_BE(AN: UInt64): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 8);
+  UInt64_To_BE(AN, LBs);
+  Result := LBs;
+end;
+
+class function TPack.UInt64_To_BE(const ANs: TCryptoLibUInt64Array): TCryptoLibByteArray;
+begin
+  Result := UInt64_To_BE(ANs, 0, System.Length(ANs));
+end;
+
+class function TPack.UInt64_To_BE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 8 * ANsLen);
+  UInt64_To_BE(ANs, ANsOff, ANsLen, LBs, 0);
+  Result := LBs;
+end;
+
+class procedure TPack.UInt64_To_BE_High(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 8 - ALen;
+  while LPos < 8 do
+  begin
+    ABs[AOff] := Byte(AN shr ((7 - LPos) * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class procedure TPack.UInt64_To_BE_Low(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    ABs[AOff] := Byte(AN shr ((ALen - 1 - LPos) * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class function TPack.BE_To_UInt64(const ABs: TCryptoLibByteArray): UInt64;
+begin
+  Result := TBinaryPrimitives.ReadUInt64BigEndian(ABs, 0);
+  //Result := BE_To_UInt64(ABs, 0);
+end;
+
+class function TPack.BE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32): UInt64;
+begin
+  Result := (UInt64(BE_To_UInt32(ABs, AOff)) shl 32) or UInt64(BE_To_UInt32(ABs, AOff + 4));
+end;
+
+class procedure TPack.BE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt64Array);
+begin
+  BE_To_UInt64(ABs, AOff, ANs, 0, System.Length(ANs));
+end;
+
+class procedure TPack.BE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array; ANsOff: Int32);
+begin
+  ANs[ANsOff] := BE_To_UInt64(ABs, ABsOff);
+end;
+
+class procedure TPack.BE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array;
+  ANsOff: Int32; ANsLen: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    ANs[ANsOff + LI] := BE_To_UInt64(ABs, ABsOff);
+    System.Inc(ABsOff, 8);
+  end;
+end;
+
+class function TPack.BE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt64Array;
+var
+  LNs: TCryptoLibUInt64Array;
+begin
+  System.SetLength(LNs, ACount);
+  BE_To_UInt64(ABs, AOff, LNs);
+  Result := LNs;
+end;
+
+class function TPack.BE_To_UInt64_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64;
+var
+  LResult: UInt64;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := (LResult shl 8) or UInt64(ABs[AOff + LPos]);
+    System.Inc(LPos);
+  end;
+
+  Result := LResult shl ((8 - ALen) * 8);
+end;
+
+class function TPack.BE_To_UInt64_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64;
+var
+  LResult: UInt64;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := (LResult shl 8) or UInt64(ABs[AOff + LPos]);
+    System.Inc(LPos);
+  end;
+
+  Result := LResult;
+end;
+
+// ---------------- Little-endian ----------------
+
+class procedure TPack.UInt16_To_LE(AN: UInt16; const ABs: TCryptoLibByteArray);
+begin
+  TBinaryPrimitives.WriteUInt16LittleEndian(ABs, 0, AN);
+  //ABs[0] := Byte(AN);
+  //ABs[1] := Byte(AN shr 8);
+end;
+
+class procedure TPack.UInt16_To_LE(AN: UInt16; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  TBinaryPrimitives.WriteUInt16LittleEndian(ABs, AOff, AN);
+  //ABs[AOff] := Byte(AN);
+  //ABs[AOff + 1] := Byte(AN shr 8);
+end;
+
+class procedure TPack.UInt16_To_LE(const ANs: TCryptoLibUInt16Array; const ABs: TCryptoLibByteArray; AOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to System.Length(ANs) - 1 do
+  begin
+    UInt16_To_LE(ANs[LI], ABs, AOff);
+    System.Inc(AOff, 2);
+  end;
+end;
+
+class procedure TPack.UInt16_To_LE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32;
+  const ABs: TCryptoLibByteArray; ABsOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    UInt16_To_LE(ANs[ANsOff + LI], ABs, ABsOff);
+    System.Inc(ABsOff, 2);
+  end;
+end;
+
+class function TPack.UInt16_To_LE(AN: UInt16): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 2);
+  UInt16_To_LE(AN, LBs);
+  Result := LBs;
+end;
+
+class function TPack.UInt16_To_LE(const ANs: TCryptoLibUInt16Array): TCryptoLibByteArray;
+begin
+  Result := UInt16_To_LE(ANs, 0, System.Length(ANs));
+end;
+
+class function TPack.UInt16_To_LE(const ANs: TCryptoLibUInt16Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 2 * ANsLen);
+  UInt16_To_LE(ANs, ANsOff, ANsLen, LBs, 0);
+  Result := LBs;
+end;
+
+class function TPack.LE_To_UInt16(const ABs: TCryptoLibByteArray): UInt16;
+begin
+  Result := TBinaryPrimitives.ReadUInt16LittleEndian(ABs, 0);
+  //Result := LE_To_UInt16(ABs, 0);
+end;
+
+class function TPack.LE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32): UInt16;
+begin
+  Result := TBinaryPrimitives.ReadUInt16LittleEndian(ABs, AOff);
+  //Result := UInt16(ABs[AOff]) or (UInt16(ABs[AOff + 1]) shl 8);
+end;
+
+class procedure TPack.LE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array; ANsOff: Int32);
+begin
+  ANs[ANsOff] := LE_To_UInt16(ABs, ABsOff);
+end;
+
+class procedure TPack.LE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt16Array);
+begin
+  LE_To_UInt16(ABs, AOff, ANs, 0, System.Length(ANs));
+end;
+
+class procedure TPack.LE_To_UInt16(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt16Array;
+  ANsOff: Int32; ANsLen: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    ANs[ANsOff + LI] := LE_To_UInt16(ABs, ABsOff);
+    System.Inc(ABsOff, 2);
+  end;
+end;
+
+class function TPack.LE_To_UInt16(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt16Array;
+var
+  LNs: TCryptoLibUInt16Array;
+begin
+  System.SetLength(LNs, ACount);
+  LE_To_UInt16(ABs, AOff, LNs);
+  Result := LNs;
+end;
+
+class procedure TPack.UInt24_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray);
+begin
+  ABs[0] := Byte(AN);
+  ABs[1] := Byte(AN shr 8);
+  ABs[2] := Byte(AN shr 16);
+end;
+
+class procedure TPack.UInt24_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  ABs[AOff] := Byte(AN);
+  ABs[AOff + 1] := Byte(AN shr 8);
+  ABs[AOff + 2] := Byte(AN shr 16);
+end;
+
+class function TPack.LE_To_UInt24(const ABs: TCryptoLibByteArray): UInt32;
+begin
+  Result := LE_To_UInt24(ABs, 0);
+end;
+
+class function TPack.LE_To_UInt24(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32;
+begin
+  Result := UInt32(ABs[AOff]) or (UInt32(ABs[AOff + 1]) shl 8) or (UInt32(ABs[AOff + 2]) shl 16);
+end;
+
+class procedure TPack.UInt32_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray);
+begin
+  TBinaryPrimitives.WriteUInt32LittleEndian(ABs, 0, AN);
+  //UInt32_To_LE(AN, ABs, 0);
+end;
+
+class procedure TPack.UInt32_To_LE(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  TBinaryPrimitives.WriteUInt32LittleEndian(ABs, AOff, AN);
+  //ABs[AOff] := Byte(AN);
+  //ABs[AOff + 1] := Byte(AN shr 8);
+  //ABs[AOff + 2] := Byte(AN shr 16);
+  //ABs[AOff + 3] := Byte(AN shr 24);
+end;
+
+class procedure TPack.UInt32_To_LE(const ANs: TCryptoLibUInt32Array; const ABs: TCryptoLibByteArray; AOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to System.Length(ANs) - 1 do
+  begin
+    UInt32_To_LE(ANs[LI], ABs, AOff);
+    System.Inc(AOff, 4);
+  end;
+end;
+
+class procedure TPack.UInt32_To_LE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32;
+  const ABs: TCryptoLibByteArray; ABsOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    UInt32_To_LE(ANs[ANsOff + LI], ABs, ABsOff);
+    System.Inc(ABsOff, 4);
+  end;
+end;
+
+class function TPack.UInt32_To_LE(AN: UInt32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 4);
+  UInt32_To_LE(AN, LBs);
+  Result := LBs;
+end;
+
+class function TPack.UInt32_To_LE(const ANs: TCryptoLibUInt32Array): TCryptoLibByteArray;
+begin
+  Result := UInt32_To_LE(ANs, 0, System.Length(ANs));
+end;
+
+class function TPack.UInt32_To_LE(const ANs: TCryptoLibUInt32Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 4 * ANsLen);
+  UInt32_To_LE(ANs, ANsOff, ANsLen, LBs, 0);
+  Result := LBs;
+end;
+
+class procedure TPack.UInt32_To_LE_High(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 4 - ALen;
+  while LPos < 4 do
+  begin
+    ABs[AOff] := Byte(AN shr (LPos * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class procedure TPack.UInt32_To_LE_Low(AN: UInt32; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    ABs[AOff] := Byte(AN shr (LPos * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class function TPack.LE_To_UInt32(const ABs: TCryptoLibByteArray): UInt32;
+begin
+  Result := TBinaryPrimitives.ReadUInt32LittleEndian(ABs, 0);
+  //Result := LE_To_UInt32(ABs, 0);
+end;
+
+class function TPack.LE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32): UInt32;
+begin
+  Result := TBinaryPrimitives.ReadUInt32LittleEndian(ABs, AOff);
+  //Result := UInt32(ABs[AOff]) or (UInt32(ABs[AOff + 1]) shl 8) or
+  //          (UInt32(ABs[AOff + 2]) shl 16) or (UInt32(ABs[AOff + 3]) shl 24);
+end;
+
+class procedure TPack.LE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt32Array);
+begin
+  LE_To_UInt32(ABs, AOff, ANs, 0, System.Length(ANs));
+end;
+
+class procedure TPack.LE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array; ANsOff: Int32);
+begin
+  ANs[ANsOff] := LE_To_UInt32(ABs, ABsOff);
+end;
+
+class procedure TPack.LE_To_UInt32(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt32Array;
+  ANsOff: Int32; ANsLen: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    ANs[ANsOff + LI] := LE_To_UInt32(ABs, ABsOff);
+    System.Inc(ABsOff, 4);
+  end;
+end;
+
+class function TPack.LE_To_UInt32(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt32Array;
+var
+  LNs: TCryptoLibUInt32Array;
+begin
+  System.SetLength(LNs, ACount);
+  LE_To_UInt32(ABs, AOff, LNs);
+  Result := LNs;
+end;
+
+class function TPack.LE_To_UInt32_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32;
+var
+  LResult: UInt32;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := LResult or (UInt32(ABs[AOff + LPos]) shl (LPos * 8));
+    System.Inc(LPos);
+  end;
+
+  Result := LResult shl ((4 - ALen) * 8);
+end;
+
+class function TPack.LE_To_UInt32_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt32;
+var
+  LResult: UInt32;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 4) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := LResult or (UInt32(ABs[AOff + LPos]) shl (LPos * 8));
+    System.Inc(LPos);
+  end;
+
+  Result := LResult;
+end;
+
+class procedure TPack.UInt64_To_LE(AN: UInt64; const ABs: TCryptoLibByteArray);
+begin
+  TBinaryPrimitives.WriteUInt64LittleEndian(ABs, 0, AN);
+  //UInt64_To_LE(AN, ABs, 0);
+end;
+
+class procedure TPack.UInt64_To_LE(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32);
+begin
+  TBinaryPrimitives.WriteUInt64LittleEndian(ABs, AOff, AN);
+  //UInt32_To_LE(UInt32(AN), ABs, AOff);
+  //UInt32_To_LE(UInt32(AN shr 32), ABs, AOff + 4);
+end;
+
+class procedure TPack.UInt64_To_LE(const ANs: TCryptoLibUInt64Array; const ABs: TCryptoLibByteArray; AOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to System.Length(ANs) - 1 do
+  begin
+    UInt64_To_LE(ANs[LI], ABs, AOff);
+    System.Inc(AOff, 8);
+  end;
+end;
+
+class procedure TPack.UInt64_To_LE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32;
+  const ABs: TCryptoLibByteArray; ABsOff: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    UInt64_To_LE(ANs[ANsOff + LI], ABs, ABsOff);
+    System.Inc(ABsOff, 8);
+  end;
+end;
+
+class function TPack.UInt64_To_LE(AN: UInt64): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 8);
+  UInt64_To_LE(AN, LBs);
+  Result := LBs;
+end;
+
+class function TPack.UInt64_To_LE(const ANs: TCryptoLibUInt64Array): TCryptoLibByteArray;
+begin
+  Result := UInt64_To_LE(ANs, 0, System.Length(ANs));
+end;
+
+class function TPack.UInt64_To_LE(const ANs: TCryptoLibUInt64Array; ANsOff: Int32; ANsLen: Int32): TCryptoLibByteArray;
+var
+  LBs: TCryptoLibByteArray;
+begin
+  System.SetLength(LBs, 8 * ANsLen);
+  UInt64_To_LE(ANs, ANsOff, ANsLen, LBs, 0);
+  Result := LBs;
+end;
+
+class procedure TPack.UInt64_To_LE_High(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 8 - ALen;
+  while LPos < 8 do
+  begin
+    ABs[AOff] := Byte(AN shr (LPos * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class procedure TPack.UInt64_To_LE_Low(AN: UInt64; const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32);
+var
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    ABs[AOff] := Byte(AN shr (LPos * 8));
+    System.Inc(AOff);
+    System.Inc(LPos);
+  end;
+end;
+
+class function TPack.LE_To_UInt64(const ABs: TCryptoLibByteArray): UInt64;
+begin
+  Result := TBinaryPrimitives.ReadUInt64LittleEndian(ABs, 0);
+  //Result := LE_To_UInt64(ABs, 0);
+end;
+
+class function TPack.LE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32): UInt64;
+begin
+  Result := TBinaryPrimitives.ReadUInt64LittleEndian(ABs, AOff);
+  //Result := UInt64(LE_To_UInt32(ABs, AOff)) or (UInt64(LE_To_UInt32(ABs, AOff + 4)) shl 32);
+end;
+
+class procedure TPack.LE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; const ANs: TCryptoLibUInt64Array);
+begin
+  LE_To_UInt64(ABs, AOff, ANs, 0, System.Length(ANs));
+end;
+
+class procedure TPack.LE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array; ANsOff: Int32);
+begin
+  ANs[ANsOff] := LE_To_UInt64(ABs, ABsOff);
+end;
+
+class procedure TPack.LE_To_UInt64(const ABs: TCryptoLibByteArray; ABsOff: Int32; const ANs: TCryptoLibUInt64Array;
+  ANsOff: Int32; ANsLen: Int32);
+var
+  LI: Int32;
+begin
+  for LI := 0 to ANsLen - 1 do
+  begin
+    ANs[ANsOff + LI] := LE_To_UInt64(ABs, ABsOff);
+    System.Inc(ABsOff, 8);
+  end;
+end;
+
+class function TPack.LE_To_UInt64(const ABs: TCryptoLibByteArray; AOff: Int32; ACount: Int32): TCryptoLibUInt64Array;
+var
+  LNs: TCryptoLibUInt64Array;
+begin
+  System.SetLength(LNs, ACount);
+  LE_To_UInt64(ABs, AOff, LNs);
+  Result := LNs;
+end;
+
+class function TPack.LE_To_UInt64_High(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64;
+var
+  LResult: UInt64;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := LResult or (UInt64(ABs[AOff + LPos]) shl (LPos * 8));
+    System.Inc(LPos);
+  end;
+
+  Result := LResult shl ((8 - ALen) * 8);
+end;
+
+class function TPack.LE_To_UInt64_Low(const ABs: TCryptoLibByteArray; AOff: Int32; ALen: Int32): UInt64;
+var
+  LResult: UInt64;
+  LPos: Int32;
+begin
+  if (ALen < 1) or (ALen > 8) then
+    raise EArgumentOutOfRangeCryptoLibException.Create('len');
+
+  LResult := 0;
+  LPos := 0;
+  while LPos < ALen do
+  begin
+    LResult := LResult or (UInt64(ABs[AOff + LPos]) shl (LPos * 8));
+    System.Inc(LPos);
+  end;
+
+  Result := LResult;
+end;
+
+end.
+

+ 10 - 0
CryptoLib/src/GeneralUtilities/ClpCryptoLibTypes.pas

@@ -113,6 +113,11 @@ type
   /// </summary>
   TCryptoLibInt64Array = TArray<Int64>;
 
+  /// <summary>
+  /// Represents a dynamic array of UInt16.
+  /// </summary>
+  TCryptoLibUInt16Array = TArray<UInt16>;
+
   /// <summary>
   /// Represents a dynamic array of UInt32.
   /// </summary>
@@ -179,6 +184,11 @@ type
   /// </summary>
   TCryptoLibInt64Array = array of Int64;
 
+  /// <summary>
+  /// Represents a dynamic array of UInt16.
+  /// </summary>
+  TCryptoLibUInt16Array = array of UInt16;
+
   /// <summary>
   /// Represents a dynamic array of UInt32.
   /// </summary>

+ 16 - 42
CryptoLib/src/Math/ClpBigInteger.pas

@@ -25,7 +25,7 @@ uses
   SysUtils,
   Math,
   ClpCryptoLibTypes,
-  ClpConverters,
+  ClpPack,
   ClpBitUtilities,
   ClpArrayUtilities,
   ClpISecureRandom,
@@ -628,7 +628,6 @@ class function TBigInteger.MakeMagnitudeBE(const ABytes: TCryptoLibByteArray; co
 var
   LEnd, LStart, LNBytes, LNInts, LFirst, I: Int32;
   LMagnitude: TCryptoLibUInt32Array;
-  LPBytes: PByte;
 begin
   LEnd := AOffset + ALength;
   // strip leading zeros
@@ -646,21 +645,9 @@ begin
   LNInts := (LNBytes + BytesPerInt - 1) div BytesPerInt;
   System.SetLength(LMagnitude, LNInts);
   LFirst := ((LNBytes - 1) mod BytesPerInt) + 1;
-  LPBytes := @ABytes[LStart];
-  // Read first partial UInt32
-  if LFirst = 1 then
-    LMagnitude[0] := UInt32(LPBytes^)
-  else if LFirst = 2 then
-    LMagnitude[0] := (UInt32(LPBytes^) shl 8) or UInt32((LPBytes + 1)^)
-  else if LFirst = 3 then
-    LMagnitude[0] := (UInt32(LPBytes^) shl 16) or (UInt32((LPBytes + 1)^) shl 8) or UInt32((LPBytes + 2)^)
-  else
-    LMagnitude[0] := TConverters.ReadBytesAsUInt32BE(LPBytes, 0);
-  // Read remaining full UInt32s
-  for I := 1 to System.Pred(LNInts) do
-  begin
-    LMagnitude[I] := TConverters.ReadBytesAsUInt32BE(LPBytes, LFirst + (I - 1) * BytesPerInt);
-  end;
+
+  LMagnitude[0] := TPack.BE_To_UInt32_Low(ABytes, LStart, LFirst);
+  TPack.BE_To_UInt32(ABytes, LStart + LFirst, LMagnitude, 1, LNInts - 1);
   Result := LMagnitude;
 end;
 
@@ -668,7 +655,6 @@ class function TBigInteger.MakeMagnitudeLE(const ABytes: TCryptoLibByteArray; co
 var
   LLast, LNInts, LPartial, LFirst, LPos, I: Int32;
   LMagnitude: TCryptoLibUInt32Array;
-  LPBytes: PByte;
 begin
   // strip leading zeros (from the end in little-endian)
   LLast := ALength;
@@ -687,23 +673,13 @@ begin
   LPartial := LLast mod BytesPerInt;
   LFirst := LPartial + 1;
   LPos := AOffset + LLast - LPartial;
-  LPBytes := @ABytes[LPos];
-  // Read first partial UInt32
- // LMagnitude[0] := TConverters.ReadBytesAsUInt32LE(LPBytes, LFirst);
-  // Read first partial UInt32
-  if LFirst = 1 then
-    LMagnitude[0] := UInt32(LPBytes^)
-  else if LFirst = 2 then
-    LMagnitude[0] := UInt32(LPBytes^) or (UInt32((LPBytes + 1)^) shl 8)
-  else if LFirst = 3 then
-    LMagnitude[0] := UInt32(LPBytes^) or (UInt32((LPBytes + 1)^) shl 8) or (UInt32((LPBytes + 2)^) shl 16)
-  else
-    LMagnitude[0] := TConverters.ReadBytesAsUInt32LE(LPBytes, 0);
-  // Read remaining full UInt32s
+
+  LMagnitude[0] := TPack.LE_To_UInt32_Low(ABytes, LPos, LFirst);
+
   for I := 1 to System.Pred(LNInts) do
   begin
     LPos := LPos - BytesPerInt;
-    LMagnitude[I] := TConverters.ReadBytesAsUInt32LE(@ABytes[LPos], 0);
+    LMagnitude[I] := TPack.LE_To_UInt32(ABytes, LPos);
   end;
   Result := LMagnitude;
 end;
@@ -887,10 +863,8 @@ begin
   if LNBits = 0 then
   begin
     System.SetLength(LNewMag, LMagLen + LNInts);
-    for I := 0 to System.Pred(LMagLen) do
-    begin
-      LNewMag[I] := AMag[I];
-    end;
+    if LMagLen > 0 then
+      Move(AMag[0], LNewMag[0], LMagLen * SizeOf(UInt32));
     TArrayUtilities.Fill<UInt32>(LNewMag, LMagLen, System.Length(LNewMag), UInt32(0));
   end
   else
@@ -1301,7 +1275,7 @@ end;
 
 function TBigInteger.LastNBits(const AN: Int32): TCryptoLibUInt32Array;
 var
-  LNumWords, LExcessBits, I: Int32;
+  LNumWords, LExcessBits, LSourceIndex: Int32;
 begin
   if AN < 1 then
   begin
@@ -1313,10 +1287,10 @@ begin
   LNumWords := Math.Min(LNumWords, System.Length(FMagnitude));
   System.SetLength(Result, LNumWords);
 
-  // Copy last LNumWords from magnitude to result
-  for I := 0 to System.Pred(LNumWords) do
+  if LNumWords > 0 then
   begin
-    Result[I] := FMagnitude[System.Length(FMagnitude) - LNumWords + I];
+    LSourceIndex := System.Length(FMagnitude) - LNumWords;
+    Move(FMagnitude[LSourceIndex], Result[0], LNumWords * SizeOf(UInt32));
   end;
 
   // Mask excess bits from result[0]
@@ -3248,7 +3222,7 @@ begin
       System.Dec(LMagIndex);
       LMag := FMagnitude[LMagIndex];
       LBytesIndex := LBytesIndex - 4;
-      TConverters.ReadUInt32AsBytesBE(LMag, Result, LBytesIndex);
+      TPack.UInt32_To_BE(LMag, Result, LBytesIndex);
     end;
     LLastMag := FMagnitude[0];
     while LLastMag > Byte.MaxValue do
@@ -3274,7 +3248,7 @@ begin
         LCarry := (LMag = UInt32.MinValue);
       end;
       LBytesIndex := LBytesIndex - 4;
-      TConverters.ReadUInt32AsBytesBE(LMag, Result, LBytesIndex);
+      TPack.UInt32_To_BE(LMag, Result, LBytesIndex);
     end;
     LLastMag := FMagnitude[0];
     if LCarry then