Explorar el Código

Sync CryptoLib and SimpleBaseLib with parent version

CryptoLib - add CTSBlockCipher Mode Support
SimpleBaseLib - Base58 decoding buffer size is now correctly calculated for all cases
Ugochukwu Mmaduekwe hace 6 años
padre
commit
7514b5f87c

+ 2 - 1
src/libraries/cryptolib4pascal/ClpAesEngine.pas

@@ -221,7 +221,6 @@ type
 
     function GetAlgorithmName: String; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
-    function GetBlockSize(): Int32; virtual;
 
     /// <summary>
     /// <para>
@@ -284,6 +283,8 @@ type
 
     procedure Reset(); virtual;
 
+    function GetBlockSize(): Int32; virtual;
+
     property AlgorithmName: String read GetAlgorithmName;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
   end;

+ 3 - 2
src/libraries/cryptolib4pascal/ClpAesLightEngine.pas

@@ -17,7 +17,7 @@
 
 unit ClpAesLightEngine;
 
-{$I ..\..\Include\CryptoLib.inc}
+{$I CryptoLib.inc}
 
 interface
 
@@ -129,7 +129,6 @@ type
 
     function GetAlgorithmName: String; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
-    function GetBlockSize(): Int32; virtual;
 
     /// <summary>
     /// <para>
@@ -192,6 +191,8 @@ type
 
     procedure Reset(); virtual;
 
+    function GetBlockSize(): Int32; virtual;
+
     property AlgorithmName: String read GetAlgorithmName;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
 

+ 5 - 1
src/libraries/cryptolib4pascal/ClpBigInteger.pas

@@ -305,13 +305,14 @@ type
     class procedure ShiftRightOneInPlace(start: Int32;
       const mag: TCryptoLibInt32Array); static;
 
+{$IFNDEF _FIXINSIGHT_}
     /// <summary>
     /// returns x = x - y - we assume x is &gt;= y
     /// </summary>
     class function Subtract(xStart: Int32; const x: TCryptoLibInt32Array;
       yStart: Int32; const y: TCryptoLibInt32Array): TCryptoLibInt32Array;
       overload; static;
-
+{$ENDIF}
     class function doSubBigLil(const bigMag, lilMag: TCryptoLibInt32Array)
       : TCryptoLibInt32Array; static; inline;
 
@@ -2739,6 +2740,8 @@ begin
   Result := TBigInteger.Create(1, yVal, True);
 end;
 
+{$IFNDEF _FIXINSIGHT_}
+
 class function TBigInteger.Subtract(xStart: Int32;
   const x: TCryptoLibInt32Array; yStart: Int32; const y: TCryptoLibInt32Array)
   : TCryptoLibInt32Array;
@@ -2780,6 +2783,7 @@ begin
 
   Result := x;
 end;
+{$ENDIF}
 
 class procedure TBigInteger.MontgomeryReduce(const x, m: TCryptoLibInt32Array;
   mDash: UInt32);

+ 353 - 39
src/libraries/cryptolib4pascal/ClpBlockCipherModes.pas

@@ -25,6 +25,7 @@ uses
   Math,
   SysUtils,
   ClpIBlockCipher,
+  ClpBufferedBlockCipher,
   ClpICipherParameters,
   ClpIParametersWithIV,
   ClpArrayUtils,
@@ -43,6 +44,9 @@ resourcestring
     'CTR/SIC mode requires IV no greater than: %u bytes';
   SInvalidTooSmallIVLength = 'CTR/SIC mode requires IV of at least: %u bytes';
 {$ENDIF}
+  SUnsupportedCipher = 'CtsBlockCipher Can Only Accept ECB or CBC Ciphers';
+  SNegativeInputLength = 'Can''t Have a Negative Input Length!';
+  SCTSDoFinalError = 'Need at Least One Block of Input For CTS';
 
 type
 
@@ -613,6 +617,98 @@ type
 
   end;
 
+type
+
+  /// <summary>
+  /// A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+  /// be used to produce cipher text which is the same outLength as the plain
+  /// text.
+  /// </summary>
+  TCtsBlockCipher = class sealed(TBufferedBlockCipher, ICtsBlockCipher)
+
+  strict private
+    FblockSize: Int32;
+
+  public
+
+    /// <summary>
+    /// Create a buffered block cipher that uses Cipher Text Stealing
+    /// </summary>
+    /// <param name="cipher">
+    /// the underlying block cipher this buffering object wraps.
+    /// </param>
+    constructor Create(const cipher: IBlockCipher);
+
+    /// <summary>
+    /// return the size of the output buffer required for an update plus a
+    /// doFinal with an input of len bytes.
+    /// </summary>
+    /// <param name="inputLen">
+    /// the outLength of the input.
+    /// </param>
+    /// <returns>
+    /// the space required to accommodate a call to update and doFinal with
+    /// length bytes of input.
+    /// </returns>
+    function GetOutputSize(inputLen: Int32): Int32; override;
+
+    /// <summary>
+    /// return the size of the output buffer required for an update an input
+    /// of len bytes.
+    /// </summary>
+    /// <param name="inputLen">
+    /// the outLength of the input.
+    /// </param>
+    /// <returns>
+    /// the space required to accommodate a call to update with length bytes
+    /// of input.
+    /// </returns>
+    function GetUpdateOutputSize(inputLen: Int32): Int32; override;
+
+    function ProcessByte(input: Byte; const output: TCryptoLibByteArray;
+      outOff: Int32): Int32; override;
+
+    /// <summary>
+    /// process an array of bytes, producing output if necessary.
+    /// </summary>
+    /// <param name="input">
+    /// the input byte array.
+    /// </param>
+    /// <param name="inOff">
+    /// the offset at which the input data starts.
+    /// </param>
+    /// <param name="Length">
+    /// the number of bytes to be copied out of the input array.
+    /// </param>
+    /// <param name="output">
+    /// the space for any output that might be produced.
+    /// </param>
+    /// <param name="outOff">
+    /// the offset from which the output will be copied.
+    /// </param>
+    /// <returns>
+    /// the number of output bytes copied to out.
+    /// </returns>
+    function ProcessBytes(const input: TCryptoLibByteArray; inOff, len: Int32;
+      const output: TCryptoLibByteArray; outOff: Int32): Int32; override;
+
+    /// <summary>
+    /// Process the last block in the buffer.
+    /// </summary>
+    /// <param name="output">
+    /// the array the block currently being held is copied into.
+    /// </param>
+    /// <param name="outOff">
+    /// the offset at which the copying starts.
+    /// </param>
+    /// <returns>
+    /// the number of output bytes copied to out.
+    /// </returns>
+    function DoFinal(const output: TCryptoLibByteArray; outOff: Int32)
+      : Int32; override;
+
+  end;
+
 implementation
 
 { TCbcBlockCipher }
@@ -631,17 +727,17 @@ end;
 function TCbcBlockCipher.DecryptBlock(const input: TCryptoLibByteArray;
   inOff: Int32; const outBytes: TCryptoLibByteArray; outOff: Int32): Int32;
 var
-  length, I: Int32;
+  Length, I: Int32;
   tmp: TCryptoLibByteArray;
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
 
   System.Move(input[inOff], FcbcNextV[0], FblockSize * System.SizeOf(Byte));
 
-  length := Fcipher.ProcessBlock(input, inOff, outBytes, outOff);
+  Length := Fcipher.ProcessBlock(input, inOff, outBytes, outOff);
 
 
   // XOR the FcbcV and the output
@@ -666,7 +762,7 @@ function TCbcBlockCipher.EncryptBlock(const input: TCryptoLibByteArray;
 var
   I, &length: Int32;
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
@@ -683,7 +779,7 @@ begin
 
   // copy ciphertext to FcbcV
 
-  System.Move(outBytes[outOff], FcbcV[0], System.length(FcbcV) *
+  System.Move(outBytes[outOff], FcbcV[0], System.Length(FcbcV) *
     System.SizeOf(Byte));
 
   result := &length;
@@ -691,8 +787,8 @@ end;
 
 procedure TCbcBlockCipher.Reset;
 begin
-  System.Move(FIV[0], FcbcV[0], System.length(FIV));
-  TArrayUtils.Fill(FcbcNextV, 0, System.length(FcbcNextV), Byte(0));
+  System.Move(FIV[0], FcbcV[0], System.Length(FIV));
+  TArrayUtils.Fill(FcbcNextV, 0, System.Length(FcbcNextV), Byte(0));
 
   Fcipher.Reset();
 end;
@@ -733,12 +829,12 @@ begin
   begin
     iv := ivParam.GetIV();
 
-    if (System.length(iv) <> FblockSize) then
+    if (System.Length(iv) <> FblockSize) then
     begin
       raise EArgumentCryptoLibException.CreateRes(@SInvalidIVLength);
     end;
 
-    System.Move(iv[0], FIV[0], System.length(iv) * System.SizeOf(Byte));
+    System.Move(iv[0], FIV[0], System.Length(iv) * System.SizeOf(Byte));
 
     Lparameters := ivParam.parameters;
   end;
@@ -789,12 +885,12 @@ function TCfbBlockCipher.DecryptBlock(const input: TCryptoLibByteArray;
 var
   I, count: Int32;
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
 
-  if ((outOff + FblockSize) > System.length(outBytes)) then
+  if ((outOff + FblockSize) > System.Length(outBytes)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
@@ -804,13 +900,13 @@ begin
   //
   // change over the input block.
   //
-  count := (System.length(FcfbV) - FblockSize) * System.SizeOf(Byte);
+  count := (System.Length(FcfbV) - FblockSize) * System.SizeOf(Byte);
   if count > 0 then
   begin
     System.Move(FcfbV[FblockSize], FcfbV[0], count);
   end;
 
-  System.Move(input[inOff], FcfbV[(System.length(FcfbV) - FblockSize)],
+  System.Move(input[inOff], FcfbV[(System.Length(FcfbV) - FblockSize)],
     FblockSize * System.SizeOf(Byte));
 
   // XOR the FcfbV with the ciphertext producing the plaintext
@@ -828,12 +924,12 @@ function TCfbBlockCipher.EncryptBlock(const input: TCryptoLibByteArray;
 var
   I, count: Int32;
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
 
-  if ((outOff + FblockSize) > System.length(outBytes)) then
+  if ((outOff + FblockSize) > System.Length(outBytes)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
@@ -850,14 +946,14 @@ begin
   //
   // change over the input block.
   //
-  count := (System.length(FcfbV) - FblockSize) * System.SizeOf(Byte);
+  count := (System.Length(FcfbV) - FblockSize) * System.SizeOf(Byte);
 
   if count > 0 then
   begin
     System.Move(FcfbV[FblockSize], FcfbV[0], count);
   end;
 
-  System.Move(outBytes[outOff], FcfbV[(System.length(FcfbV) - FblockSize)],
+  System.Move(outBytes[outOff], FcfbV[(System.Length(FcfbV) - FblockSize)],
     FblockSize * System.SizeOf(Byte));
 
   result := FblockSize;
@@ -865,7 +961,7 @@ end;
 
 procedure TCfbBlockCipher.Reset;
 begin
-  System.Move(FIV[0], FcfbV[0], System.length(FIV));
+  System.Move(FIV[0], FcfbV[0], System.Length(FIV));
 
   Fcipher.Reset();
 end;
@@ -905,9 +1001,9 @@ begin
   begin
     iv := ivParam.GetIV();
 
-    diff := System.length(FIV) - System.length(iv);
+    diff := System.Length(FIV) - System.Length(iv);
 
-    System.Move(iv[0], FIV[diff], System.length(iv) * System.SizeOf(Byte));
+    System.Move(iv[0], FIV[diff], System.Length(iv) * System.SizeOf(Byte));
     TArrayUtils.Fill(FIV, 0, diff, Byte(0));
 
     Lparameters := ivParam.parameters;
@@ -952,7 +1048,7 @@ end;
 
 procedure TOfbBlockCipher.Reset;
 begin
-  System.Move(FIV[0], FofbV[0], System.length(FIV));
+  System.Move(FIV[0], FofbV[0], System.Length(FIV));
 
   Fcipher.Reset();
 
@@ -994,13 +1090,13 @@ begin
   begin
     iv := ivParam.GetIV();
 
-    if (System.length(iv) < System.length(FIV)) then
+    if (System.Length(iv) < System.Length(FIV)) then
     begin
       // prepend the supplied IV with zeros (per FIPS PUB 81)
-      System.Move(iv[0], FIV[System.length(FIV) - System.length(iv)],
-        System.length(iv) * System.SizeOf(Byte));
+      System.Move(iv[0], FIV[System.Length(FIV) - System.Length(iv)],
+        System.Length(iv) * System.SizeOf(Byte));
 
-      for I := 0 to System.Pred(System.length(FIV) - System.length(iv)) do
+      for I := 0 to System.Pred(System.Length(FIV) - System.Length(iv)) do
       begin
         FIV[I] := 0;
       end;
@@ -1008,7 +1104,7 @@ begin
     end
     else
     begin
-      System.Move(iv[0], FIV[0], System.length(FIV) * System.SizeOf(Byte));
+      System.Move(iv[0], FIV[0], System.Length(FIV) * System.SizeOf(Byte));
     end;
 
     Lparameters := ivParam.parameters;
@@ -1029,12 +1125,12 @@ function TOfbBlockCipher.ProcessBlock(const input: TCryptoLibByteArray;
 var
   I, count: Int32;
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
 
-  if ((outOff + FblockSize) > System.length(output)) then
+  if ((outOff + FblockSize) > System.Length(output)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
@@ -1054,14 +1150,14 @@ begin
   //
   // change over the input block.
   //
-  count := (System.length(FofbV) - FblockSize) * System.SizeOf(Byte);
+  count := (System.Length(FofbV) - FblockSize) * System.SizeOf(Byte);
 
   if count > 0 then
   begin
     System.Move(FofbV[FblockSize], FofbV[0], count);
   end;
 
-  System.Move(FofbOutV[0], FofbV[(System.length(FofbV) - FblockSize)],
+  System.Move(FofbOutV[0], FofbV[(System.Length(FofbV) - FblockSize)],
     FblockSize * System.SizeOf(Byte));
 
   result := FblockSize;
@@ -1082,8 +1178,8 @@ end;
 
 procedure TSicBlockCipher.Reset;
 begin
-  TArrayUtils.Fill(Fcounter, 0, System.length(Fcounter), Byte(0));
-  System.Move(FIV[0], Fcounter[0], System.length(FIV) * System.SizeOf(Byte));
+  TArrayUtils.Fill(Fcounter, 0, System.Length(Fcounter), Byte(0));
+  System.Move(FIV[0], Fcounter[0], System.Length(FIV) * System.SizeOf(Byte));
 
   Fcipher.Reset();
 
@@ -1125,7 +1221,7 @@ begin
   begin
     FIV := ivParam.GetIV();
 
-    if (FblockSize < System.length(FIV)) then
+    if (FblockSize < System.Length(FIV)) then
     begin
       raise EArgumentCryptoLibException.CreateResFmt(@SInvalidTooLargeIVLength,
         [FblockSize]);
@@ -1133,7 +1229,7 @@ begin
 
     maxCounterSize := Min(8, FblockSize div 2);
 
-    if ((FblockSize - System.length(FIV)) > maxCounterSize) then
+    if ((FblockSize - System.Length(FIV)) > maxCounterSize) then
     begin
       raise EArgumentCryptoLibException.CreateResFmt(@SInvalidTooSmallIVLength,
         [FblockSize - maxCounterSize]);
@@ -1163,12 +1259,12 @@ var
   I, J: Int32;
 begin
 
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
 
-  if ((outOff + FblockSize) > System.length(output)) then
+  if ((outOff + FblockSize) > System.Length(output)) then
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
@@ -1178,14 +1274,14 @@ begin
   //
   // XOR the counterOut with the plaintext producing the cipher text
   //
-  for I := 0 to System.Pred(System.length(FcounterOut)) do
+  for I := 0 to System.Pred(System.Length(FcounterOut)) do
   begin
 
     output[outOff + I] := Byte(FcounterOut[I] xor input[inOff + I]);
   end;
 
   // Increment the counter
-  J := System.length(Fcounter);
+  J := System.Length(Fcounter);
   System.Dec(J);
   System.Inc(Fcounter[J]);
   while ((J >= 0) and (Fcounter[J] = 0)) do
@@ -1194,7 +1290,225 @@ begin
     System.Inc(Fcounter[J]);
   end;
 
-  result := System.length(Fcounter);
+  result := System.Length(Fcounter);
+end;
+
+{ TCtsBlockCipher }
+
+constructor TCtsBlockCipher.Create(const cipher: IBlockCipher);
+begin
+  Inherited Create();
+  if Supports(cipher, ICfbBlockCipher) or Supports(cipher, IOfbBlockCipher) or
+    Supports(cipher, ISicBlockCipher) or Supports(cipher, ICtsBlockCipher) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SUnsupportedCipher);
+  end;
+
+  Fcipher := cipher;
+
+  FblockSize := Fcipher.GetBlockSize();
+  System.SetLength(Fbuf, FblockSize * 2);
+  FbufOff := 0;
+end;
+
+function TCtsBlockCipher.DoFinal(const output: TCryptoLibByteArray;
+  outOff: Int32): Int32;
+var
+  blockSize, len, I: Int32;
+  block, lastBlock: TCryptoLibByteArray;
+  c: IBlockCipher;
+begin
+  if ((FbufOff + outOff) > System.Length(output)) then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes
+      (@SOutputBufferTooSmallForDoFinal);
+  end;
+
+  blockSize := Fcipher.GetBlockSize();
+  len := FbufOff - blockSize;
+  System.SetLength(block, blockSize);
+
+  if (FforEncryption) then
+  begin
+    if (FbufOff < blockSize) then
+    begin
+      raise EDataLengthCryptoLibException.CreateRes(@SCTSDoFinalError);
+    end;
+
+    Fcipher.ProcessBlock(Fbuf, 0, block, 0);
+
+    if (FbufOff > blockSize) then
+    begin
+
+      I := FbufOff;
+      while I <> System.Length(Fbuf) do
+      begin
+        Fbuf[I] := block[I - blockSize];
+        System.Inc(I);
+      end;
+
+      I := blockSize;
+      while I <> FbufOff do
+      begin
+        Fbuf[I] := Fbuf[I] xor (block[I - blockSize]);
+        System.Inc(I);
+      end;
+
+      if Supports(Fcipher, ICbcBlockCipher) then
+      begin
+        c := (Fcipher as ICbcBlockCipher).GetUnderlyingCipher();
+
+        c.ProcessBlock(Fbuf, blockSize, output, outOff);
+      end
+      else
+      begin
+        Fcipher.ProcessBlock(Fbuf, blockSize, output, outOff);
+      end;
+
+      System.Move(block[0], output[outOff + blockSize],
+        len * System.SizeOf(Byte));
+    end
+    else
+    begin
+      System.Move(block[0], output[outOff], blockSize * System.SizeOf(Byte));
+    end;
+  end
+  else
+  begin
+
+    if (FbufOff < blockSize) then
+    begin
+      raise EDataLengthCryptoLibException.CreateRes(@SCTSDoFinalError);
+    end;
+
+    System.SetLength(lastBlock, blockSize);
+
+    if (FbufOff > blockSize) then
+    begin
+
+      if Supports(Fcipher, ICbcBlockCipher) then
+      begin
+        c := (Fcipher as ICbcBlockCipher).GetUnderlyingCipher();
+
+        c.ProcessBlock(Fbuf, 0, block, 0);
+      end
+      else
+      begin
+        Fcipher.ProcessBlock(Fbuf, 0, block, 0);
+      end;
+
+      I := blockSize;
+      while I <> FbufOff do
+      begin
+        lastBlock[I - blockSize] := Byte(block[I - blockSize] xor Fbuf[I]);
+        System.Inc(I);
+      end;
+
+      System.Move(Fbuf[blockSize], block[0], len * System.SizeOf(Byte));
+      Fcipher.ProcessBlock(block, 0, output, outOff);
+      System.Move(lastBlock[0], output[outOff + blockSize],
+        len * System.SizeOf(Byte));
+    end
+    else
+    begin
+      Fcipher.ProcessBlock(Fbuf, 0, block, 0);
+      System.Move(block[0], output[outOff], blockSize * System.SizeOf(Byte));
+    end;
+
+  end;
+
+  result := FbufOff;
+
+  Reset();
+end;
+
+function TCtsBlockCipher.GetOutputSize(inputLen: Int32): Int32;
+begin
+  result := inputLen + FbufOff;
+end;
+
+function TCtsBlockCipher.GetUpdateOutputSize(inputLen: Int32): Int32;
+var
+  total, leftOver: Int32;
+begin
+  total := inputLen + FbufOff;
+  leftOver := total mod System.Length(Fbuf);
+
+  if (leftOver = 0) then
+  begin
+    result := total - System.Length(Fbuf);
+    Exit;
+  end;
+  result := total - leftOver;
+end;
+
+function TCtsBlockCipher.ProcessByte(input: Byte;
+  const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  result := 0;
+
+  if (FbufOff = System.Length(Fbuf)) then
+  begin
+    result := Fcipher.ProcessBlock(Fbuf, 0, output, outOff);
+    System.Move(Fbuf[FblockSize], Fbuf[0], FblockSize * System.SizeOf(Byte));
+    FbufOff := FblockSize;
+  end;
+
+  Fbuf[FbufOff] := input;
+  System.Inc(FbufOff);
+end;
+
+function TCtsBlockCipher.ProcessBytes(const input: TCryptoLibByteArray;
+  inOff, len: Int32; const output: TCryptoLibByteArray; outOff: Int32): Int32;
+var
+  blockSize, Length, gapLen: Int32;
+begin
+  if (len < 0) then
+  begin
+    raise EInvalidArgument.CreateRes(@SNegativeInputLength);
+  end;
+
+  blockSize := GetBlockSize();
+  Length := GetUpdateOutputSize(len);
+
+  if (Length > 0) then
+  begin
+    if ((outOff + Length) > System.Length(output)) then
+    begin
+      raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
+    end;
+  end;
+
+  result := 0;
+  gapLen := System.Length(Fbuf) - FbufOff;
+
+  if (len > gapLen) then
+  begin
+    System.Move(input[inOff], Fbuf[FbufOff], gapLen * System.SizeOf(Byte));
+
+    result := result + Fcipher.ProcessBlock(Fbuf, 0, output, outOff);
+    System.Move(Fbuf[blockSize], Fbuf[0], blockSize * System.SizeOf(Byte));
+
+    FbufOff := blockSize;
+
+    len := len - gapLen;
+    inOff := inOff + gapLen;
+
+    while (len > blockSize) do
+    begin
+      System.Move(input[inOff], Fbuf[FbufOff], blockSize * System.SizeOf(Byte));
+      result := result + Fcipher.ProcessBlock(Fbuf, 0, output, outOff + result);
+      System.Move(Fbuf[blockSize], Fbuf[0], blockSize * System.SizeOf(Byte));
+
+      len := len - blockSize;
+      inOff := inOff + blockSize;
+    end;
+  end;
+
+  System.Move(input[inOff], Fbuf[FbufOff], len * System.SizeOf(Byte));
+
+  FbufOff := FbufOff + len;
+
 end;
 
 end.

+ 2 - 1
src/libraries/cryptolib4pascal/ClpBlowfishEngine.pas

@@ -277,7 +277,6 @@ type
 
     function GetAlgorithmName: String; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
-    function GetBlockSize(): Int32; virtual;
 
   public
 
@@ -301,6 +300,8 @@ type
 
     procedure Reset(); virtual;
 
+    function GetBlockSize(): Int32; virtual;
+
     property AlgorithmName: String read GetAlgorithmName;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
 

+ 2 - 1
src/libraries/cryptolib4pascal/ClpChaChaEngine.pas

@@ -23,6 +23,7 @@ interface
 
 uses
   SysUtils,
+  ClpIStreamCipher,
   ClpIChaChaEngine,
   ClpSalsa20Engine,
   ClpConverters,
@@ -33,7 +34,7 @@ type
   /// <summary>
   /// Implementation of Daniel J. Bernstein's ChaCha stream cipher.
   /// </summary>
-  TChaChaEngine = class sealed(TSalsa20Engine, IChaChaEngine)
+  TChaChaEngine = class sealed(TSalsa20Engine, IChaChaEngine, IStreamCipher)
 
   strict private
     /// <summary>

+ 29 - 5
src/libraries/cryptolib4pascal/ClpCipherUtilities.pas

@@ -48,6 +48,8 @@ uses
   ClpIBlowfishEngine,
   ClpSalsa20Engine,
   ClpISalsa20Engine,
+  ClpRijndaelEngine,
+  ClpIRijndaelEngine,
   ClpIBlockCipherPadding;
 
 resourcestring
@@ -70,11 +72,11 @@ type
 
   type
 {$SCOPEDENUMS ON}
-    TCipherAlgorithm = (AES, BLOWFISH, SALSA20);
-    TCipherMode = (NONE, CBC, CFB, CTR, ECB, OFB, SIC);
+    TCipherAlgorithm = (AES, BLOWFISH, SALSA20, RIJNDAEL);
+    TCipherMode = (NONE, CBC, CFB, CTR, CTS, ECB, OFB, SIC);
     TCipherPadding = (NOPADDING, ISO10126PADDING, ISO10126D2PADDING,
       ISO10126_2PADDING, ISO7816_4PADDING, ISO9797_1PADDING, PKCS5,
-      PKCS5PADDING, PKCS7, PKCS7PADDING, TBCPADDING, X923PADDING,
+      PKCS5PADDING, PKCS7, PKCS7PADDING, TBCPADDING, WITHCTS, X923PADDING,
       ZEROBYTEPADDING);
 {$SCOPEDENUMS OFF}
 
@@ -192,7 +194,7 @@ class function TCipherUtilities.GetCipher(algorithm: String): IBufferedCipher;
 var
   aliased, algorithmName, temp, paddingName, mode, modeName: string;
   di, LowPoint, bits, HighPoint: Int32;
-  padded: Boolean;
+  padded, CTS: Boolean;
   parts: TCryptoLibStringArray;
   cipherAlgorithm: TCipherAlgorithm;
   cipherPadding: TCipherPadding;
@@ -239,6 +241,10 @@ begin
       begin
         blockCipher := TBlowfishEngine.Create() as IBlowfishEngine;
       end;
+    TCipherAlgorithm.RIJNDAEL:
+      begin
+        blockCipher := TRijndaelEngine.Create() as IRijndaelEngine;
+      end;
     TCipherAlgorithm.SALSA20:
       begin
         streamCipher := TSalsa20Engine.Create() as ISalsa20Engine;
@@ -263,6 +269,7 @@ begin
     Exit;
   end;
 
+  CTS := False;
   padded := true;
   padding := Nil;
 
@@ -280,7 +287,7 @@ begin
     case cipherPadding of
       TCipherPadding.NOPADDING:
         begin
-          padded := false;
+          padded := False;
         end;
 
       TCipherPadding.ISO10126PADDING, TCipherPadding.ISO10126D2PADDING,
@@ -305,6 +312,11 @@ begin
           padding := TTBCPadding.Create() as ITBCPadding;
         end;
 
+      TCipherPadding.WITHCTS:
+        begin
+          CTS := true;
+        end;
+
       TCipherPadding.X923PADDING:
         begin
           padding := TX923Padding.Create() as IX923Padding;
@@ -393,6 +405,12 @@ begin
           blockCipher := TSicBlockCipher.Create(blockCipher) as ISicBlockCipher;
         end;
 
+      TCipherMode.CTS:
+        begin
+          CTS := true;
+          blockCipher := TCbcBlockCipher.Create(blockCipher) as ICbcBlockCipher;
+        end;
+
       TCipherMode.OFB:
         begin
           if (di < 0) then
@@ -433,6 +451,12 @@ begin
   if (blockCipher <> Nil) then
   begin
 
+    if (CTS) then
+    begin
+      Result := TCtsBlockCipher.Create(blockCipher) as ICtsBlockCipher;
+      Exit;
+    end;
+
     if (padding <> Nil) then
     begin
       Result := TPaddedBufferedBlockCipher.Create(blockCipher, padding)

+ 10 - 7
src/libraries/cryptolib4pascal/ClpECC.pas

@@ -243,7 +243,8 @@ type
 
     property Q: TBigInteger read GetQ;
 
-    function Equals(const other: IFpFieldElement): Boolean; reintroduce; overload;
+    function Equals(const other: IFpFieldElement): Boolean;
+      reintroduce; overload;
 
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}override;
@@ -393,7 +394,8 @@ type
 
     function SquarePow(pow: Int32): IECFieldElement; override;
 
-    function Equals(const other: IF2mFieldElement): Boolean; reintroduce; overload;
+    function Equals(const other: IF2mFieldElement): Boolean;
+      reintroduce; overload;
 
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}override;
@@ -1091,7 +1093,8 @@ type
     function GetIsInfinity: Boolean; inline;
     function GetIsCompressed: Boolean; inline;
     function GetpreCompTable: TDictionary<String, IPreCompInfo>; inline;
-    procedure SetpreCompTable(const Value: TDictionary<String, IPreCompInfo>); inline;
+    procedure SetpreCompTable(const Value
+      : TDictionary<String, IPreCompInfo>); inline;
     function GetCurve: IECCurve; virtual;
     function GetCurveCoordinateSystem: Int32; virtual;
     function GetAffineXCoord: IECFieldElement; virtual;
@@ -1718,8 +1721,8 @@ begin
   xx := (x as IF2mFieldElement).x;
   yx := (y as IF2mFieldElement).x;
 
-  ab := ax.Multiply(bx, Fm, FKs);
-  xy := xx.Multiply(yx, Fm, FKs);
+  ab := ax.Multiply(bx);
+  xy := xx.Multiply(yx);
 
   if ((ab.Equals(ax)) or (ab.Equals(bx))) then
   begin
@@ -1770,8 +1773,8 @@ begin
   xx := (x as IF2mFieldElement).x;
   yx := (y as IF2mFieldElement).x;
 
-  aa := ax.Square(Fm, FKs);
-  xy := xx.Multiply(yx, Fm, FKs);
+  aa := ax.Square();
+  xy := xx.Multiply(yx);
 
   if (aa.Equals(ax)) then
   begin

+ 23 - 1
src/libraries/cryptolib4pascal/ClpIBlockCipherModes.pas

@@ -22,7 +22,9 @@ unit ClpIBlockCipherModes;
 interface
 
 uses
-  ClpIBlockCipher;
+  ClpIBlockCipher,
+  ClpIBufferedBlockCipher,
+  ClpCryptoLibTypes;
 
 type
   ICbcBlockCipher = interface(IBlockCipher)
@@ -84,6 +86,26 @@ type
 
   end;
 
+type
+  ICtsBlockCipher = interface(IBufferedBlockCipher)
+
+    ['{4D02FD0B-47D6-4914-B31F-5869FF364558}']
+
+    function GetOutputSize(inputLen: Int32): Int32;
+
+    function GetUpdateOutputSize(inputLen: Int32): Int32;
+
+    function ProcessByte(input: Byte; const output: TCryptoLibByteArray;
+      outOff: Int32): Int32;
+
+    function ProcessBytes(const input: TCryptoLibByteArray;
+      inOff, Length: Int32; const output: TCryptoLibByteArray;
+      outOff: Int32): Int32;
+
+    function DoFinal(const output: TCryptoLibByteArray; outOff: Int32): Int32;
+
+  end;
+
 implementation
 
 end.

+ 1 - 1
src/libraries/cryptolib4pascal/ClpIESEngine.pas

@@ -39,7 +39,7 @@ uses
   ClpIParametersWithIV,
   ClpIKeyParser,
   ClpIEphemeralKeyPair,
-  ClpKDFParameters,
+  ClpKdfParameters,
   ClpIKdfParameters,
   ClpIIESWithCipherParameters,
   ClpConverters,

+ 36 - 0
src/libraries/cryptolib4pascal/ClpIRijndaelEngine.pas

@@ -0,0 +1,36 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRijndaelEngine;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpIBlockCipher;
+
+type
+
+  IRijndaelEngine = interface(IBlockCipher)
+    ['{F4BB47F6-082F-4318-8434-95F06C26CE77}']
+
+  end;
+
+implementation
+
+end.

+ 0 - 5
src/libraries/cryptolib4pascal/ClpISignersEncodings.pas

@@ -103,11 +103,6 @@ type
     procedure EncodeValue(const n, x: TBigInteger;
       const buf: TCryptoLibByteArray; off, len: Int32);
 
-    function Decode(const n: TBigInteger; const encoding: TCryptoLibByteArray)
-      : TCryptoLibGenericArray<TBigInteger>;
-
-    function Encode(const n, r, s: TBigInteger): TCryptoLibByteArray;
-
   end;
 
 implementation

+ 8 - 12
src/libraries/cryptolib4pascal/ClpLongArray.pas

@@ -515,8 +515,8 @@ type
     class procedure FlipVector(const x: TCryptoLibInt64Array; xOff: Int32;
       const y: TCryptoLibInt64Array; yOff, yLen, bits: Int32); static;
 
-    class procedure SquareInPlace(const x: TCryptoLibInt64Array; xLen, m: Int32;
-      const ks: TCryptoLibInt32Array); static; inline;
+    class procedure SquareInPlace(const x: TCryptoLibInt64Array; xLen: Int32);
+      static; inline;
 
     class procedure Interleave(const x: TCryptoLibInt64Array; xOff: Int32;
       const z: TCryptoLibInt64Array; zOff, count, width: Int32); static; inline;
@@ -603,8 +603,7 @@ type
     function ModReduce(m: Int32; const ks: TCryptoLibInt32Array)
       : TLongArray; inline;
 
-    function Multiply(const other: TLongArray; m: Int32;
-      const ks: TCryptoLibInt32Array): TLongArray;
+    function Multiply(const other: TLongArray): TLongArray;
 
     procedure Reduce(m: Int32; const ks: TCryptoLibInt32Array); inline;
 
@@ -614,8 +613,7 @@ type
     function ModSquareN(n, m: Int32; const ks: TCryptoLibInt32Array)
       : TLongArray; inline;
 
-    function Square(m: Int32; const ks: TCryptoLibInt32Array)
-      : TLongArray; inline;
+    function Square(): TLongArray; inline;
 
     function ModInverse(m: Int32; const ks: TCryptoLibInt32Array): TLongArray;
 
@@ -787,7 +785,7 @@ begin
 end;
 
 class procedure TLongArray.SquareInPlace(const x: TCryptoLibInt64Array;
-  xLen, m: Int32; const ks: TCryptoLibInt32Array);
+  xLen: Int32);
 var
   pos: Int32;
   xVal: Int64;
@@ -2241,7 +2239,7 @@ begin
   System.Dec(n);
   while (n >= 0) do
   begin
-    SquareInPlace(r, len, m, ks);
+    SquareInPlace(r, len);
     len := ReduceInPlace(r, 0, System.Length(r), m, ks);
     System.Dec(n);
   end;
@@ -2249,8 +2247,7 @@ begin
   Result := TLongArray.Create(r, 0, len);
 end;
 
-function TLongArray.Multiply(const other: TLongArray; m: Int32;
-  const ks: TCryptoLibInt32Array): TLongArray;
+function TLongArray.Multiply(const other: TLongArray): TLongArray;
 var
   aDeg, bDeg, tmp, aLen, bLen, cLen, bMax, tOff, I, MASK, aPos, cOff,
     u, v: Int32;
@@ -2501,8 +2498,7 @@ begin
   Result := prev;
 end;
 
-function TLongArray.Square(m: Int32; const ks: TCryptoLibInt32Array)
-  : TLongArray;
+function TLongArray.Square(): TLongArray;
 var
   len, _2len, pos: Int32;
   r: TCryptoLibInt64Array;

+ 911 - 0
src/libraries/cryptolib4pascal/ClpRijndaelEngine.pas

@@ -0,0 +1,911 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRijndaelEngine;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCheck,
+  ClpIBlockCipher,
+  ClpIRijndaelEngine,
+  ClpIKeyParameter,
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInputBuffertooShort = 'Input Buffer too Short';
+  SOutputBuffertooShort = 'Output Buffer too Short';
+  SUnsupportedBlock = 'Unknown Blocksize to Rijndael';
+  SInvalidKeyLength = 'Key Length not 128/160/192/224/256 bits.';
+  SRijndaelEngineNotInitialised = 'Rijndael Engine not Initialised';
+  SInvalidParameterRijndaelInit =
+    'Invalid Parameter Passed to Rijndael Init - "%s"';
+
+type
+
+  /// <summary>
+  /// <para>
+  /// an implementation of Rijndael, based on the documentation and
+  /// reference implementation by Paulo Barreto, Vincent Rijmen, for v2.0
+  /// August '99.
+  /// </para>
+  /// <para>
+  /// Note: this implementation is based on information prior to readonly
+  /// NIST publication.
+  /// </para>
+  /// </summary>
+  TRijndaelEngine = class(TInterfacedObject, IRijndaelEngine, IBlockCipher)
+
+  strict private
+  const
+    MAXROUNDS = Int32(14);
+    MAXKC = Int32(256 div 4);
+
+    Logtable: array [0 .. 255] of Byte = (0, 0, 25, 1, 50, 2, 26, 198, 75, 199,
+      27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8,
+      200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228,
+      166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240,
+      130, 69, 53, 147, 218, 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92,
+      210, 241, 64, 70, 131, 56, 102, 221, 253, 48, 191, 6, 139, 98, 179, 37,
+      226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, 58, 107,
+      40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212,
+      172, 229, 243, 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79,
+      174, 233, 213, 231, 230, 173, 232, 44, 215, 117, 122, 235, 22, 11, 245,
+      89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, 73, 236,
+      216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134,
+      59, 82, 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252,
+      188, 149, 207, 205, 55, 63, 91, 209, 83, 57, 132, 60, 65, 162, 109, 71,
+      20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, 217, 35, 32, 46, 137,
+      180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254,
+      24, 13, 99, 140, 128, 192, 247, 112, 7);
+
+    Alogtable: array [0 .. 510] of Byte = (0, 3, 5, 15, 17, 51, 85, 255, 26, 46,
+      114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2,
+      6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217,
+      112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104,
+      184, 211, 110, 178, 205, 76, 212, 103, 169, 224, 59, 77, 215, 98, 166,
+      241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129,
+      152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11,
+      29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47,
+      113, 147, 174, 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93,
+      231, 50, 86, 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, 64, 192, 91, 237,
+      44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, 42, 126, 130,
+      157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175,
+      234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27,
+      45, 119, 153, 176, 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145,
+      168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, 41, 123, 141, 140,
+      143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162,
+      253, 28, 36, 108, 180, 199, 82, 246, 1, 3, 5, 15, 17, 51, 85, 255, 26, 46,
+      114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2,
+      6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217,
+      112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104,
+      184, 211, 110, 178, 205, 76, 212, 103, 169, 224, 59, 77, 215, 98, 166,
+      241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129,
+      152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11,
+      29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47,
+      113, 147, 174, 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93,
+      231, 50, 86, 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, 64, 192, 91, 237,
+      44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, 42, 126, 130,
+      157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175,
+      234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27,
+      45, 119, 153, 176, 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145,
+      168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, 41, 123, 141, 140,
+      143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162,
+      253, 28, 36, 108, 180, 199, 82, 246, 1);
+
+    S: array [0 .. 255] of Byte = (99, 124, 119, 123, 242, 107, 111, 197, 48, 1,
+      103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173,
+      212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204,
+      52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7,
+      18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59,
+      214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
+      190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2,
+      127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218,
+      33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126,
+      61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184,
+      20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98,
+      145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244,
+      234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116,
+      31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185,
+      134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135,
+      233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45,
+      15, 176, 84, 187, 22);
+
+    Si: array [0 .. 255] of Byte = (82, 9, 106, 213, 48, 54, 165, 56, 191, 64,
+      163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52,
+      142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238,
+      76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91,
+      162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212,
+      164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94,
+      21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247,
+      228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175,
+      189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242,
+      207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226,
+      249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111,
+      183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154,
+      219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177,
+      18, 16, 89, 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229,
+      122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200,
+      235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225,
+      105, 20, 99, 85, 33, 12, 125);
+
+    rcon: array [0 .. 29] of Byte = ($01, $02, $04, $08, $10, $20, $40, $80,
+      $1B, $36, $6C, $D8, $AB, $4D, $9A, $2F, $5E, $BC, $63, $C6, $97, $35, $6A,
+      $D4, $B3, $7D, $FA, $EF, $C5, $91);
+
+    shifts0: array [0 .. 4, 0 .. 3] of Byte = ((0, 8, 16, 24), (0, 8, 16, 24),
+      (0, 8, 16, 24), (0, 8, 16, 32), (0, 8, 24, 32));
+
+    shifts1: array [0 .. 4, 0 .. 3] of Byte = ((0, 24, 16, 8), (0, 32, 24, 16),
+      (0, 40, 32, 24), (0, 48, 40, 24), (0, 56, 40, 32));
+
+  var
+    FForEncryption: Boolean;
+    FBC, FROUNDS, FBlockBits: Int32;
+    FBC_MASK, FA0, FA1, FA2, FA3: UInt64;
+    FShifts0SC, FShifts1SC: TCryptoLibByteArray;
+    FWorkingKey: TCryptoLibMatrixUInt64Array;
+
+    function GetAlgorithmName: String; virtual;
+    function GetIsPartialBlockOkay: Boolean; virtual;
+
+    /// <summary>
+    /// multiply two elements of GF(2^m) needed for MixColumn and
+    /// InvMixColumn
+    /// </summary>
+    function Mul0x2(b: Int32): Byte; inline;
+
+    function Mul0x3(b: Int32): Byte; inline;
+
+    function Mul0x9(b: Int32): Byte; inline;
+
+    function Mul0xb(b: Int32): Byte; inline;
+
+    function Mul0xd(b: Int32): Byte; inline;
+
+    function Mul0xe(b: Int32): Byte; inline;
+
+    /// <summary>
+    /// xor corresponding text input and round key input bytes
+    /// </summary>
+    procedure KeyAddition(const rk: TCryptoLibUInt64Array); inline;
+
+    /// <summary>
+    /// rotate right custom
+    /// </summary>
+    function Shift(r: UInt64; Shift: Int32): UInt64; inline;
+
+    /// <summary>
+    /// Row 0 remains unchanged <br />The other three rows are shifted a
+    /// variable amount
+    /// </summary>
+    procedure ShiftRow(const shiftsSC: TCryptoLibByteArray); inline;
+
+    function ApplyS(r: UInt64; box: PByte): UInt64; inline;
+
+    /// <summary>
+    /// Replace every byte of the input by the byte at that place <br />in
+    /// the nonlinear S-box
+    /// </summary>
+    procedure Substitution(box: PByte); inline;
+
+    /// <summary>
+    /// Mix the bytes of every column in a linear way
+    /// </summary>
+    procedure MixColumn();
+
+    /// <summary>
+    /// Mix the bytes of every column in a linear way <br />This is the
+    /// opposite operation of Mixcolumn
+    /// </summary>
+    procedure InvMixColumn();
+
+    /// <summary>
+    /// Calculate the necessary round keys <br />The number of calculations
+    /// depends on keyBits and blockBits
+    /// </summary>
+    function GenerateWorkingKey(const key: TCryptoLibByteArray)
+      : TCryptoLibMatrixUInt64Array;
+
+    procedure UnPackBlock(const bytes: TCryptoLibByteArray; off: Int32); inline;
+    procedure PackBlock(const bytes: TCryptoLibByteArray; off: Int32); inline;
+
+    procedure EncryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+
+    procedure DecryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+
+  public
+
+    /// <summary>
+    /// default constructor - 128 bit block size.
+    /// </summary>
+    constructor Create(); overload;
+
+    /// <summary>
+    /// basic constructor - set the cipher up for a given blocksize
+    /// </summary>
+    /// <param name="blockBits">
+    /// the blocksize in bits, must be 128, 192, or 256.
+    /// </param>
+    constructor Create(blockBits: Int32); overload;
+
+    /// <summary>
+    /// initialise a Rijndael cipher.
+    /// </summary>
+    /// <param name="forEncryption">
+    /// whether or not we are for encryption.
+    /// </param>
+    /// <param name="parameters">
+    /// the parameters required to set up the cipher.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the parameters argument is inappropriate.
+    /// </exception>
+    procedure Init(forEncryption: Boolean;
+      const parameters: ICipherParameters); virtual;
+
+    function ProcessBlock(const input: TCryptoLibByteArray; inOff: Int32;
+      const output: TCryptoLibByteArray; outOff: Int32): Int32; virtual;
+
+    procedure Reset(); virtual;
+
+    function GetBlockSize(): Int32; virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
+
+  end;
+
+implementation
+
+{ TRijndaelEngine }
+
+function TRijndaelEngine.Mul0x2(b: Int32): Byte;
+begin
+  if (b <> 0) then
+  begin
+    result := Alogtable[25 + (Logtable[b] and $FF)];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0x3(b: Int32): Byte;
+begin
+  if (b <> 0) then
+  begin
+    result := Alogtable[1 + (Logtable[b] and $FF)];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0x9(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[199 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0xb(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[104 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0xd(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[238 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0xe(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[223 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+procedure TRijndaelEngine.KeyAddition(const rk: TCryptoLibUInt64Array);
+begin
+  FA0 := FA0 xor rk[0];
+  FA1 := FA1 xor rk[1];
+  FA2 := FA2 xor rk[2];
+  FA3 := FA3 xor rk[3];
+end;
+
+function TRijndaelEngine.Shift(r: UInt64; Shift: Int32): UInt64;
+begin
+  result := (((r shr Shift) or (r shl (FBC - Shift)))) and FBC_MASK;
+end;
+
+procedure TRijndaelEngine.ShiftRow(const shiftsSC: TCryptoLibByteArray);
+begin
+  FA1 := Shift(FA1, shiftsSC[1]);
+  FA2 := Shift(FA2, shiftsSC[2]);
+  FA3 := Shift(FA3, shiftsSC[3]);
+end;
+
+function TRijndaelEngine.ApplyS(r: UInt64; box: PByte): UInt64;
+var
+  j: Int32;
+begin
+  result := 0;
+  j := 0;
+  while j < FBC do
+  begin
+    result := result or (UInt64(box[((r shr j) and $FF)] and $FF) shl j);
+    System.Inc(j, 8);
+  end;
+end;
+
+procedure TRijndaelEngine.Substitution(box: PByte);
+begin
+  FA0 := ApplyS(FA0, box);
+  FA1 := ApplyS(FA1, box);
+  FA2 := ApplyS(FA2, box);
+  FA3 := ApplyS(FA3, box);
+end;
+
+procedure TRijndaelEngine.MixColumn;
+var
+  r0, r1, r2, r3: UInt64;
+  a0, a1, a2, a3, j: Int32;
+begin
+  r0 := 0;
+  r1 := 0;
+  r2 := 0;
+  r3 := 0;
+  j := 0;
+  while j < FBC do
+  begin
+
+    a0 := Int32((FA0 shr j) and $FF);
+    a1 := Int32((FA1 shr j) and $FF);
+    a2 := Int32((FA2 shr j) and $FF);
+    a3 := Int32((FA3 shr j) and $FF);
+
+    r0 := r0 or (UInt64(((Mul0x2(a0) xor Mul0x3(a1) xor a2 xor a3) and
+      $FF)) shl j);
+
+    r1 := r1 or (UInt64(((Mul0x2(a1) xor Mul0x3(a2) xor a3 xor a0) and
+      $FF)) shl j);
+
+    r2 := r2 or (UInt64(((Mul0x2(a2) xor Mul0x3(a3) xor a0 xor a1) and
+      $FF)) shl j);
+
+    r3 := r3 or (UInt64(((Mul0x2(a3) xor Mul0x3(a0) xor a1 xor a2) and
+      $FF)) shl j);
+
+    System.Inc(j, 8);
+  end;
+
+  FA0 := r0;
+  FA1 := r1;
+  FA2 := r2;
+  FA3 := r3;
+end;
+
+procedure TRijndaelEngine.InvMixColumn;
+var
+  r0, r1, r2, r3: UInt64;
+  a0, a1, a2, a3, j: Int32;
+begin
+  r0 := 0;
+  r1 := 0;
+  r2 := 0;
+  r3 := 0;
+  j := 0;
+  while j < FBC do
+  begin
+
+    a0 := Int32((FA0 shr j) and $FF);
+    a1 := Int32((FA1 shr j) and $FF);
+    a2 := Int32((FA2 shr j) and $FF);
+    a3 := Int32((FA3 shr j) and $FF);
+
+    //
+    // pre-lookup the log table
+    //
+    if (a0 <> 0) then
+    begin
+      a0 := (Logtable[a0 and $FF] and $FF);
+    end
+    else
+    begin
+      a0 := -1;
+    end;
+
+    if (a1 <> 0) then
+    begin
+      a1 := (Logtable[a1 and $FF] and $FF);
+    end
+    else
+    begin
+      a1 := -1;
+    end;
+
+    if (a2 <> 0) then
+    begin
+      a2 := (Logtable[a2 and $FF] and $FF);
+    end
+    else
+    begin
+      a2 := -1;
+    end;
+
+    if (a3 <> 0) then
+    begin
+      a3 := (Logtable[a3 and $FF] and $FF);
+    end
+    else
+    begin
+      a3 := -1;
+    end;
+
+    r0 := r0 or
+      (UInt64(((Mul0xe(a0) xor Mul0xb(a1) xor Mul0xd(a2) xor Mul0x9(a3)) and
+      $FF)) shl j);
+
+    r1 := r1 or
+      (UInt64(((Mul0xe(a1) xor Mul0xb(a2) xor Mul0xd(a3) xor Mul0x9(a0)) and
+      $FF)) shl j);
+
+    r2 := r2 or
+      (UInt64(((Mul0xe(a2) xor Mul0xb(a3) xor Mul0xd(a0) xor Mul0x9(a1)) and
+      $FF)) shl j);
+
+    r3 := r3 or
+      (UInt64(((Mul0xe(a3) xor Mul0xb(a0) xor Mul0xd(a1) xor Mul0x9(a2)) and
+      $FF)) shl j);
+
+    System.Inc(j, 8);
+  end;
+
+  FA0 := r0;
+  FA1 := r1;
+  FA2 := r2;
+  FA3 := r3;
+end;
+
+function TRijndaelEngine.GenerateWorkingKey(const key: TCryptoLibByteArray)
+  : TCryptoLibMatrixUInt64Array;
+var
+  KC, t, rconpointer, keyBits, i, index, j: Int32;
+  tk: TCryptoLibMatrixByteArray;
+  W: TCryptoLibMatrixUInt64Array;
+begin
+  rconpointer := 0;
+  keyBits := System.Length(key) * 8;
+  System.SetLength(tk, 4);
+  for i := System.Low(tk) to System.High(tk) do
+  begin
+    System.SetLength(tk[i], MAXKC);
+  end;
+
+  System.SetLength(W, MAXROUNDS + 1);
+  for i := System.Low(W) to System.High(W) do
+  begin
+    System.SetLength(W[i], 4);
+  end;
+
+  case keyBits of
+    128:
+      KC := 4;
+    160:
+      KC := 5;
+    192:
+      KC := 6;
+    224:
+      KC := 7;
+    256:
+      KC := 8
+  else
+    begin
+      raise EArgumentCryptoLibException.CreateRes(@SInvalidKeyLength);
+    end;
+  end;
+
+  if (keyBits >= FBlockBits) then
+  begin
+    FROUNDS := KC + 6;
+  end
+  else
+  begin
+    FROUNDS := (FBC div 8) + 6;
+  end;
+
+  //
+  // copy the key into the processing area
+  //
+  index := 0;
+
+  for i := 0 to System.Pred(System.Length(key)) do
+  begin
+    tk[i mod 4][i div 4] := key[index];
+    System.Inc(index);
+  end;
+
+  t := 0;
+  //
+  // copy values into round key array
+  //
+  j := 0;
+
+  while ((j < KC) and (t < ((FROUNDS + 1) * (FBC div 8)))) do
+  begin
+    for i := 0 to System.Pred(4) do
+    begin
+      W[t div (FBC div 8)][i] := W[t div (FBC div 8)][i] or
+        (UInt64(tk[i][j] and $FF) shl ((t * 8) mod FBC));
+    end;
+    System.Inc(j);
+    System.Inc(t);
+  end;
+
+  //
+  // while not enough round key material calculated
+  // calculate new values
+  //
+  while (t < ((FROUNDS + 1) * (FBC div 8))) do
+  begin
+
+    for i := 0 to System.Pred(4) do
+    begin
+      tk[i][0] := tk[i][0] xor (S[tk[(i + 1) mod 4][KC - 1] and $FF]);
+    end;
+
+    tk[0][0] := tk[0][0] xor Byte(rcon[rconpointer]);
+    System.Inc(rconpointer);
+
+    if (KC <= 6) then
+    begin
+      for j := 1 to System.Pred(KC) do
+      begin
+        for i := 0 to System.Pred(4) do
+        begin
+          tk[i][j] := tk[i][j] xor tk[i][j - 1];
+        end;
+      end;
+    end
+    else
+    begin
+
+      for j := 1 to System.Pred(4) do
+      begin
+        for i := 0 to System.Pred(4) do
+        begin
+          tk[i][j] := tk[i][j] xor tk[i][j - 1];
+        end;
+      end;
+
+      for i := 0 to System.Pred(4) do
+      begin
+        tk[i][4] := tk[i][4] xor (S[tk[i][3] and $FF]);
+      end;
+
+      for j := 5 to System.Pred(KC) do
+      begin
+        for i := 0 to System.Pred(4) do
+        begin
+          tk[i][j] := tk[i][j] xor tk[i][j - 1];
+        end;
+      end;
+    end;
+
+    //
+    // copy values into round key array
+    //
+    j := 0;
+
+    while ((j < KC) and (t < ((FROUNDS + 1) * (FBC div 8)))) do
+    begin
+      for i := 0 to System.Pred(4) do
+      begin
+        W[t div (FBC div 8)][i] := W[t div (FBC div 8)][i] or
+          (UInt64(tk[i][j] and $FF) shl ((t * 8) mod FBC));
+      end;
+      System.Inc(j);
+      System.Inc(t);
+    end;
+  end;
+  result := W;
+end;
+
+procedure TRijndaelEngine.PackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+var
+  index, j: Int32;
+begin
+  index := off;
+  j := 0;
+
+  while j <> FBC do
+  begin
+    bytes[index] := Byte(FA0 shr j);
+    System.Inc(index);
+    bytes[index] := Byte(FA1 shr j);
+    System.Inc(index);
+    bytes[index] := Byte(FA2 shr j);
+    System.Inc(index);
+    bytes[index] := Byte(FA3 shr j);
+    System.Inc(index);
+    System.Inc(j, 8);
+  end;
+end;
+
+procedure TRijndaelEngine.UnPackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+var
+  index, j: Int32;
+begin
+  index := off;
+
+  FA0 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+  FA1 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+  FA2 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+  FA3 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+
+  j := 8;
+
+  while j <> FBC do
+  begin
+    FA0 := FA0 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    FA1 := FA1 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    FA2 := FA2 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    FA3 := FA3 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    System.Inc(j, 8);
+  end;
+end;
+
+procedure TRijndaelEngine.EncryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+var
+  r: Int32;
+begin
+  //
+  // begin with a key addition
+  //
+  KeyAddition(rk[0]);
+
+  //
+  // ROUNDS-1 ordinary rounds
+  //
+  for r := 1 to System.Pred(FROUNDS) do
+  begin
+    Substitution(@(S[0]));
+    ShiftRow(FShifts0SC);
+    MixColumn();
+    KeyAddition(rk[r]);
+  end;
+
+  //
+  // Last round is special: there is no MixColumn
+  //
+  Substitution(@(S[0]));
+  ShiftRow(FShifts0SC);
+  KeyAddition(rk[FROUNDS]);
+end;
+
+procedure TRijndaelEngine.DecryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+var
+  r: Int32;
+begin
+  // To decrypt: apply the inverse operations of the encrypt routine,
+  // in opposite order
+  //
+  // (KeyAddition is an involution: it 's equal to its inverse)
+  // (the inverse of Substitution with table S is Substitution with the inverse table of S)
+  // (the inverse of Shiftrow is Shiftrow over a suitable distance)
+  //
+
+  // First the special round:
+  // without InvMixColumn
+  // with extra KeyAddition
+  //
+  KeyAddition(rk[FROUNDS]);
+  Substitution(@(Si[0]));
+  ShiftRow(FShifts1SC);
+
+  //
+  // ROUNDS-1 ordinary rounds
+  //
+  for r := System.Pred(FROUNDS) downto 1 do
+  begin
+    KeyAddition(rk[r]);
+    InvMixColumn();
+    Substitution(@(Si[0]));
+    ShiftRow(FShifts1SC);
+  end;
+
+  //
+  // End with the extra key addition
+  //
+  KeyAddition(rk[0]);
+end;
+
+constructor TRijndaelEngine.Create();
+begin
+  Create(128);
+end;
+
+constructor TRijndaelEngine.Create(blockBits: Int32);
+begin
+  Inherited Create();
+  case blockBits of
+
+    128:
+      begin
+        FBC := 32;
+        FBC_MASK := $FFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[0]));
+        System.Move(shifts0[0], FShifts0SC[0], System.SizeOf(shifts0[0]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[0]));
+        System.Move(shifts1[0], FShifts1SC[0], System.SizeOf(shifts1[0]));
+      end;
+
+    160:
+      begin
+        FBC := 40;
+        FBC_MASK := $FFFFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[1]));
+        System.Move(shifts0[1], FShifts0SC[0], System.SizeOf(shifts0[1]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[1]));
+        System.Move(shifts1[1], FShifts1SC[0], System.SizeOf(shifts1[1]));
+      end;
+
+    192:
+      begin
+        FBC := 48;
+        FBC_MASK := $FFFFFFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[2]));
+        System.Move(shifts0[2], FShifts0SC[0], System.SizeOf(shifts0[2]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[2]));
+        System.Move(shifts1[2], FShifts1SC[0], System.SizeOf(shifts1[2]));
+      end;
+
+    224:
+      begin
+        FBC := 56;
+        FBC_MASK := $FFFFFFFFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[3]));
+        System.Move(shifts0[3], FShifts0SC[0], System.SizeOf(shifts0[3]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[3]));
+        System.Move(shifts1[3], FShifts1SC[0], System.SizeOf(shifts1[3]));
+      end;
+
+    256:
+      begin
+        FBC := 64;
+        FBC_MASK := UInt64($FFFFFFFFFFFFFFFF);
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[4]));
+        System.Move(shifts0[4], FShifts0SC[0], System.SizeOf(shifts0[4]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[4]));
+        System.Move(shifts1[4], FShifts1SC[0], System.SizeOf(shifts1[4]));
+      end
+  else
+    begin
+      raise EArgumentOutOfRangeCryptoLibException.CreateRes(@SUnsupportedBlock);
+    end;
+
+  end;
+
+  FBlockBits := blockBits;
+end;
+
+function TRijndaelEngine.GetAlgorithmName: String;
+begin
+  result := 'Rijndael';
+end;
+
+function TRijndaelEngine.GetBlockSize: Int32;
+begin
+  result := FBC div 2;
+end;
+
+function TRijndaelEngine.GetIsPartialBlockOkay: Boolean;
+begin
+  result := False;
+end;
+
+procedure TRijndaelEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  keyParameter: IKeyParameter;
+begin
+  if not Supports(parameters, IKeyParameter, keyParameter) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidParameterRijndaelInit, [(parameters as TObject).ToString]);
+  end;
+
+  FWorkingKey := GenerateWorkingKey(keyParameter.GetKey());
+
+  FForEncryption := forEncryption;
+end;
+
+function TRijndaelEngine.ProcessBlock(const input: TCryptoLibByteArray;
+  inOff: Int32; const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  if (FWorkingKey = Nil) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SRijndaelEngineNotInitialised);
+  end;
+
+  TCheck.DataLength(input, inOff, (FBC div 2), SInputBuffertooShort);
+  TCheck.OutputLength(output, outOff, (FBC div 2), SOutputBuffertooShort);
+
+  UnPackBlock(input, inOff);
+
+  if (FForEncryption) then
+  begin
+    EncryptBlock(FWorkingKey);
+  end
+  else
+  begin
+    DecryptBlock(FWorkingKey);
+  end;
+
+  PackBlock(output, outOff);
+
+  result := FBC div 2;
+end;
+
+procedure TRijndaelEngine.Reset;
+begin
+
+end;
+
+end.

+ 2 - 2
src/libraries/cryptolib4pascal/ClpSalsa20Engine.pas

@@ -25,10 +25,10 @@ uses
   SysUtils,
   ClpBits,
   ClpCheck,
+  ClpIStreamCipher,
   ClpISalsa20Engine,
   ClpIKeyParameter,
   ClpICipherParameters,
-  ClpParametersWithIV,
   ClpIParametersWithIV,
   ClpConverters,
   ClpCryptoLibTypes;
@@ -56,7 +56,7 @@ type
   /// <summary>
   /// Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
   /// </summary>
-  TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine)
+  TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher)
 
   strict private
   const

+ 0 - 1
src/libraries/cryptolib4pascal/ClpSchnorrDigestSigner.pas

@@ -32,7 +32,6 @@ uses
   ClpBigInteger,
   ClpCryptoLibTypes,
   ClpIParametersWithRandom,
-  ClpSignersEncodings,
   ClpIAsymmetricKeyParameter,
   ClpICipherParameters,
   ClpISigner;

+ 2 - 1
src/libraries/cryptolib4pascal/ClpXSalsa20Engine.pas

@@ -22,6 +22,7 @@ unit ClpXSalsa20Engine;
 interface
 
 uses
+  ClpIStreamCipher,
   ClpSalsa20Engine,
   ClpIXSalsa20Engine,
   ClpConverters,
@@ -38,7 +39,7 @@ type
   /// <remarks>
   /// XSalsa20 requires a 256 bit key, and a 192 bit nonce.
   /// </remarks>
-  TXSalsa20Engine = class sealed(TSalsa20Engine, IXSalsa20Engine)
+  TXSalsa20Engine = class sealed(TSalsa20Engine, IXSalsa20Engine, IStreamCipher)
 
   strict protected
     function GetAlgorithmName: String; override;

+ 1 - 1
src/libraries/cryptolib4pascal/README.md

@@ -1,5 +1,5 @@
 # CryptoLib4Pascal [![License](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Xor-el/CryptoLib4Pascal/blob/master/LICENSE)
-CryptoLib4Pascal is a Cryptographic Package for Delphi/FreePascal Compilers that provides at the moment support for creating, signing and verifying DSA, ECDSA, ECNR and ECSchnorr signatures using various curves and hashes, AES, Blowfish Encryption and Decryption (With various modes and paddings) and ECIES.
+CryptoLib4Pascal is a Cryptographic Package for Delphi/FreePascal Compilers that provides at the moment support for creating, signing and verifying DSA, ECDSA, ECNR and ECSchnorr signatures using various curves and hashes, AES, Rijndael, Blowfish and Speck Block Encryption and Decryption (With various modes and paddings), Salsa20, XSalsa20, ChaCha Stream Ciphers and ECIES.
 
 **Supported Elliptic Curves:**
 

+ 4 - 1
src/libraries/simplebaselib4pascal/SbpBase58.pas

@@ -5,6 +5,7 @@ unit SbpBase58;
 interface
 
 uses
+  Math,
   SbpSimpleBaseLibTypes,
   SbpUtilities,
   SbpBase58Alphabet,
@@ -94,6 +95,7 @@ const
   reductionFactor = Int32(733);
 var
   textLen, numZeroes, outputLen, carry, resultLen, LowPoint: Int32;
+  tempDouble: Double;
   inputPtr, pEnd, pInput: PChar;
   outputPtr, pOutputEnd, pDigit, pOutput: PByte;
   FirstChar, c: Char;
@@ -130,7 +132,8 @@ begin
     Exit;
   end;
 
-  outputLen := ((textLen * reductionFactor) div 1000) + 1;
+  tempDouble := ((textLen * reductionFactor) / 1000.0) + 1;
+  outputLen := Int32(Round(tempDouble));
   table := Falphabet.ReverseLookupTable;
   System.SetLength(output, outputLen);
   outputPtr := PByte(output);