Subversion Repositories decoder

Rev

Blame | Last modification | View Log | RSS feed

  1. {Copyright:      Hagen Reddmann HaReddmann at T-Online dot de
  2.  Author:         Hagen Reddmann
  3.  Remarks:        freeware, but this Copyright must be included
  4.  known Problems: none
  5.  Version:        5.1,  Part I from Delphi Encryption Compendium  ( DEC Part I)
  6.                  Delphi 5
  7.  
  8.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
  9.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  11.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
  12.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  13.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  14.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  15.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  16.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  17.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  18.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  19. }
  20.  
  21. unit DECCipher;
  22.  
  23. interface
  24.  
  25. uses SysUtils, Classes, DECUtil, DECFmt;
  26.  
  27. {$I VER.INC}
  28.  
  29. type
  30.   TCipher_Null         = class;  // Null cipher, does'nt encrypt, copying only
  31.   TCipher_Blowfish     = class;
  32.   TCipher_Twofish      = class;  {AES Round 2 Final Candidate}
  33.   TCipher_IDEA         = class;
  34.   TCipher_Cast256      = class;
  35.   TCipher_Mars         = class;  {AES Round 2 Final Candidate}
  36.   TCipher_RC4          = class;  {Streamcipher in as Block Cipher}
  37.   TCipher_RC6          = class;  {AES Round 2 Final Candidate}
  38.   TCipher_Rijndael     = class;  {AES Round 2 Final Candidate}
  39.   TCipher_Square       = class;
  40.   TCipher_SCOP         = class;  {Streamcipher on Longword, very fast}
  41.   TCipher_Sapphire     = class;  {Stream Cipher, eq. Design from german ENIGMA Machine}
  42.   TCipher_1DES         = class;  {Single DES  8 byte Blocksize,  8 byte Keysize  56 bits relevant}
  43.   TCipher_2DES         = class;  {Triple DES  8 byte Blocksize, 16 byte Keysize 112 bits relevant}
  44.   TCipher_3DES         = class;  {Triple DES  8 byte Blocksize, 24 byte Keysize 168 bits relevant}
  45.   TCipher_2DDES        = class;  {Triple DES 16 byte Blocksize, 16 byte Keysize 112 bits relevant}
  46.   TCipher_3DDES        = class;  {Triple DES 16 byte Blocksize, 24 byte Keysize 168 bits relevant}
  47.   TCipher_3TDES        = class;  {Triple DES 24 byte Blocksize, 24 byte Keysize 168 bits relevant}
  48.   TCipher_3Way         = class;
  49.   TCipher_Cast128      = class;
  50.   TCipher_Gost         = class;
  51.   TCipher_Misty        = class;
  52.   TCipher_NewDES       = class;
  53.   TCipher_Q128         = class;
  54.   TCipher_RC2          = class;
  55.   TCipher_RC5          = class;
  56.   TCipher_SAFER        = class;
  57.   TCipher_Shark        = class;
  58.   TCipher_Skipjack     = class;
  59.   TCipher_TEA          = class;
  60.   TCipher_TEAN         = class;
  61.  
  62.   TCipherContext = packed record
  63.     KeySize: Integer;            // maximal key size in bytes
  64.     BlockSize: Integer;          // mininmal block size in bytes, eg. 1 = Streamcipher
  65.     BufferSize: Integer;         // internal buffersize in bytes
  66.     UserSize: Integer;           // internal size in bytes of cipher dependend structures
  67.     UserSave: Boolean;          
  68.   end;
  69.  
  70.   TCipherState = (csNew, csInitialized, csEncode, csDecode, csPadded, csDone);
  71.   TCipherStates = set of TCipherState;
  72. { TCipher.State represents the internal state of processing
  73.   csNew         = cipher isn't initialized, .Init() must be called before en/decode
  74.   csInitialized = cipher is initialized by .Init(), eg. Keysetup was processed
  75.   csEncode      = Encodeing was started, and more chunks can be encoded, but not decoded
  76.   csDecode      = Decodeing was started, and more chunks can be decoded, but not encoded
  77.   csPadded      = trough En/Decodeing the messagechunks are padded, no more chunks can
  78.                   be processed, the cipher is blocked.
  79.   csDone        = Processing is finished and Cipher.Done was called. Now new En/Decoding
  80.                   can be started without calling .Init() before. csDone is basicaly
  81.                   identical to csInitialized, except Cipher.Buffer holds the encrypted
  82.                   last state of Cipher.Feedback, thus Cipher.Buffer can be used as C-MAC.}
  83.  
  84.   TCipherMode = (cmCTSx, cmCBCx, cmCFB8, cmCFBx, cmOFB8, cmOFBx, cmCFS8, cmCFSx, cmECBx);
  85. { cmCTSx = double CBC, with CFS8 padding of truncated final block
  86.   cmCBCx = Cipher Block Chainung, with CFB8 padding of truncated final block
  87.   cmCFB8 = 8bit Cipher Feedback mode
  88.   cmCFBx = CFB on Blocksize of Cipher
  89.   cmOFB8 = 8bit Output Feedback mode
  90.   cmOFBx = OFB on Blocksize bytes
  91.   cmCFS8 = 8Bit CFS, double CFB
  92.   cmCFSx = CFS on Blocksize bytes
  93.   cmECBx = Electronic Code Book
  94.  
  95.   Modes cmCBCx, cmCTSx, cmCFBx, cmOFBx, cmCFSx, cmECBx working on Blocks of
  96.   Cipher.BufferSize bytes, on Blockcipher that's equal to Cipher.BlockSize.
  97.  
  98.   Modes cmCFB8, cmOFB8, cmCFS8 work on 8 bit Feedback Shift Registers.
  99.  
  100.   Modes cmCTSx, cmCFSx, cmCFS8 are prohibitary modes developed by me. These modes
  101.   works such as cmCBCx, cmCFBx, cmCFB8 but with double XOR'ing of the inputstream
  102.   into Feedback register.
  103.  
  104.   Mode cmECBx need message padding to a multiple of Cipher.BlockSize and should
  105.   be only used in 1byte Streamciphers.
  106.  
  107.   Modes cmCTSx, cmCBCx need no external padding, because internal the last truncated
  108.   block is padded by cmCFS8 or cmCFB8. After padding these Mode can't be used to
  109.   process more data. If it needed to process chunks of data then each chunk must
  110.   be algined to Cipher.BufferSize bytes.
  111.  
  112.   Modes cmCFBx,cmCFB8,cmOFBx,cmOFB8,cmCFSx,cmCFS8 need no padding.
  113.  
  114. }
  115.   TDECCipherCodeEvent = procedure(const Source; var Dest; DataSize: Integer) of object;
  116.  
  117.   TDECCipherClass = class of TDECCipher;
  118.  
  119.   TDECCipher = class(TDECObject)
  120.   private
  121.     FState: TCipherState;
  122.     FMode: TCipherMode;
  123.     FData: PByteArray;
  124.     FDataSize: Integer;
  125.     procedure SetMode(Value: TCipherMode);
  126.   protected
  127.     FBufferSize: Integer;
  128.     FBufferIndex: Integer;
  129.     FUserSize: Integer;
  130.     FBuffer: PByteArray;
  131.     FVector: PByteArray;
  132.     FFeedback: PByteArray;
  133.     FUser: Pointer;
  134.     FUserSave: Pointer;
  135.     procedure CheckState(States: TCipherStates);
  136.     procedure DoInit(const Key; Size: Integer); virtual; abstract;
  137.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); virtual; abstract;
  138.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); virtual; abstract;
  139.   public
  140.     constructor Create; override;
  141.     destructor Destroy; override;
  142.  
  143.     class function Context: TCipherContext; virtual; abstract;
  144.  
  145.     procedure Init(const Key; Size: Integer; const IVector; IVectorSize: Integer; IFiller: Byte = $FF); overload;
  146.     procedure Init(const Key: Binary; const IVector: Binary = ''; IFiller: Byte = $FF); overload;
  147.     procedure Done;
  148.     procedure Protect; virtual;
  149.  
  150.     procedure Encode(const Source; var Dest; DataSize: Integer);
  151.     procedure Decode(const Source; var Dest; DataSize: Integer);
  152.  
  153.     function  EncodeBinary(const Source: Binary; Format: TDECFormatClass = nil): Binary;
  154.     function  DecodeBinary(const Source: Binary; Format: TDECFormatClass = nil): Binary;
  155.     procedure EncodeFile(const Source, Dest: String; const Progress: IDECProgress = nil);
  156.     procedure DecodeFile(const Source, Dest: String; const Progress: IDECProgress = nil);
  157.     procedure EncodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress = nil);
  158.     procedure DecodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress = nil);
  159.  
  160.     function  CalcMAC(Format: TDECFormatClass = nil): Binary;
  161.  
  162.     property InitVectorSize: Integer read FBufferSize;
  163.     property InitVector: PByteArray read FVector; // buffer size bytes
  164.     property Feedback: PByteArray read FFeedback; // buffer size bytes
  165.  
  166.     property State: TCipherState read FState;
  167.   published
  168.     property Mode: TCipherMode read FMode write SetMode;
  169.   end;
  170.  
  171.   TCipher_Null = class(TDECCipher)
  172.   protected
  173.     procedure DoInit(const Key; Size: Integer); override;
  174.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  175.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  176.   public
  177.     class function Context: TCipherContext; override;
  178.   end;
  179.  
  180.   TCipher_Blowfish = class(TDECCipher)
  181.   protected
  182.     procedure DoInit(const Key; Size: Integer); override;
  183.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  184.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  185.   public
  186.     class function Context: TCipherContext; override;
  187.   end;
  188.  
  189.   TCipher_Twofish = class(TDECCipher)
  190.   protected
  191.     procedure DoInit(const Key; Size: Integer); override;
  192.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  193.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  194.   public
  195.     class function Context: TCipherContext; override;
  196.   end;
  197.  
  198.   TCipher_IDEA = class(TDECCipher) {International Data Encryption Algorithm }
  199.   protected
  200.     procedure DoInit(const Key; Size: Integer); override;
  201.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  202.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  203.   public
  204.     class function Context: TCipherContext; override;
  205.   end;
  206.  
  207.   TCipher_Cast256 = class(TDECCipher)
  208.   protected
  209.     procedure DoInit(const Key; Size: Integer); override;
  210.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  211.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  212.   public
  213.     class function Context: TCipherContext; override;
  214.   end;
  215.  
  216.   TCipher_Mars = class(TDECCipher)
  217.   protected
  218.     procedure DoInit(const Key; Size: Integer); override;
  219.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  220.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  221.   public
  222.     class function Context: TCipherContext; override;
  223.   end;
  224.  
  225.   TCipher_RC4 = class(TDECCipher)
  226.   protected
  227.     procedure DoInit(const Key; Size: Integer); override;
  228.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  229.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  230.   public
  231.     class function Context: TCipherContext; override;
  232.   end;
  233.  
  234.   TCipher_RC6 = class(TDECCipher)
  235.   private
  236.     FRounds: Integer; {16-24, default 20}
  237.     procedure SetRounds(Value: Integer);
  238.   protected
  239.     procedure DoInit(const Key; Size: Integer); override;
  240.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  241.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  242.   public
  243.     class function Context: TCipherContext; override;
  244.   published
  245.     property Rounds: Integer read FRounds write SetRounds;
  246.   end;
  247.  
  248.   TCipher_Rijndael = class(TDECCipher)
  249.   private
  250.     FRounds: Integer;
  251.   protected
  252.     procedure DoInit(const Key; Size: Integer); override;
  253.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  254.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  255.   public
  256.     class function Context: TCipherContext; override;
  257.   published
  258.     property Rounds: Integer read FRounds;
  259.   end;
  260.  
  261.   TCipher_Square = class(TDECCipher)
  262.   protected
  263.     procedure DoInit(const Key; Size: Integer); override;
  264.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  265.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  266.   public
  267.     class function Context: TCipherContext; override;
  268.   end;
  269.  
  270.   TCipher_SCOP = class(TDECCipher) {Stream Cipher in Blockmode}
  271.   protected
  272.     procedure DoInit(const Key; Size: Integer); override;
  273.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  274.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  275.   public
  276.     class function Context: TCipherContext; override;
  277.   end;
  278.  
  279.   TCipher_Sapphire = class(TDECCipher)
  280.   protected
  281.     procedure DoInit(const Key; Size: Integer); override;
  282.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  283.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  284.   public
  285.     class function Context: TCipherContext; override;
  286.   end;
  287.  
  288.   TCipher_1DES = class(TDECCipher)
  289.   protected
  290.     procedure DoInitKey(const Data: array of Byte; Key: PLongArray; Reverse: Boolean);
  291.     procedure DoInit(const Key; Size: Integer); override;
  292.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  293.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  294.   public
  295.     class function Context: TCipherContext; override;
  296.   end;
  297.  
  298.   TCipher_2DES = class(TCipher_1DES)
  299.   protected
  300.     procedure DoInit(const Key; Size: Integer); override;
  301.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  302.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  303.   public
  304.     class function Context: TCipherContext; override;
  305.   end;
  306.  
  307.   TCipher_3DES = class(TCipher_1DES)
  308.   protected
  309.     procedure DoInit(const Key; Size: Integer); override;
  310.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  311.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  312.   public
  313.     class function Context: TCipherContext; override;
  314.   end;
  315.  
  316.   TCipher_2DDES = class(TCipher_2DES)
  317.   protected
  318.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  319.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  320.   public
  321.     class function Context: TCipherContext; override;
  322.   end;
  323.  
  324.   TCipher_3DDES = class(TCipher_3DES)
  325.   protected
  326.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  327.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  328.   public
  329.     class function Context: TCipherContext; override;
  330.   end;
  331.  
  332.   TCipher_3TDES = class(TCipher_3DES)
  333.   protected
  334.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  335.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  336.   public
  337.     class function Context: TCipherContext; override;
  338.   end;
  339.  
  340.   TCipher_3Way = class(TDECCipher)
  341.   protected
  342.     procedure DoInit(const Key; Size: Integer); override;
  343.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  344.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  345.   public
  346.     class function Context: TCipherContext; override;
  347.   end;
  348.  
  349.   TCipher_Cast128 = class(TDECCipher) {Carlisle Adams and Stafford Tavares }
  350.   private
  351.     FRounds: Integer;
  352.     procedure SetRounds(Value: Integer);
  353.   protected
  354.     procedure DoInit(const Key; Size: Integer); override;
  355.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  356.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  357.   public
  358.     class function Context: TCipherContext; override;
  359.   published
  360.     property Rounds: Integer read FRounds write SetRounds;
  361.   end;
  362.  
  363.   TCipher_Gost = class(TDECCipher) {russian Cipher}
  364.   protected
  365.     procedure DoInit(const Key; Size: Integer); override;
  366.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  367.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  368.   public
  369.     class function Context: TCipherContext; override;
  370.   end;
  371.  
  372.   TCipher_Misty = class(TDECCipher)
  373.   protected
  374.     procedure DoInit(const Key; Size: Integer); override;
  375.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  376.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  377.   public
  378.     class function Context: TCipherContext; override;
  379.   end;
  380.  
  381. { This algorithm resembles the Data Encryption Standard (DES), but is easier
  382.   to implement in software and is supposed to be more secure.
  383.   It is not to be confused with another algorithm--known by the
  384.   same name--which is simply DES without the initial and final
  385.   permutations.  The NewDES here is a completely different algorithm.}
  386.  
  387.   TCipher_NewDES = class(TDECCipher)
  388.   protected
  389.     procedure DoInit(const Key; Size: Integer); override;
  390.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  391.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  392.   public
  393.     class function Context: TCipherContext; override;
  394.   end;
  395.  
  396.   TCipher_Q128 = class(TDECCipher)
  397.   protected
  398.     procedure DoInit(const Key; Size: Integer); override;
  399.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  400.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  401.   public
  402.     class function Context: TCipherContext; override;
  403.   end;
  404.  
  405.   TCipher_RC2 = class(TDECCipher)
  406.   protected
  407.     procedure DoInit(const Key; Size: Integer); override;
  408.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  409.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  410.   public
  411.     class function Context: TCipherContext; override;
  412.   end;
  413.  
  414.   TCipher_RC5 = class(TDECCipher)
  415.   private
  416.     FRounds: Integer; {8-16, default 12}
  417.     procedure SetRounds(Value: Integer);
  418.   protected
  419.     procedure DoInit(const Key; Size: Integer); override;
  420.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  421.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  422.   public
  423.     class function Context: TCipherContext; override;
  424.   published
  425.     property Rounds: Integer read FRounds write SetRounds;
  426.   end;
  427.  
  428.   TSAFERVersion = (svSK128, svSK64, svSK40, svK128, svK64, svK40);
  429. {svK40       SAFER K-40    Keysize is 40bit  ->  5 Byte
  430.  svK64       SAFER K-64    Keysize is 64bit  ->  8 Byte
  431.  svK128      SAFER K-128   KeySize is 128bit -> 16 Byte
  432.  svSK40      SAFER SK-40   stronger Version from K-40 with better Keyscheduling
  433.  svSK64      SAFER SK-64   stronger Version from K-64 with better Keyscheduling
  434.  svSK128     SAFER SK-128  stronger Version from K-128 with better Keyscheduling}
  435.  
  436.   TCipher_SAFER = class(TDECCipher) {SAFER = Secure And Fast Encryption Routine}
  437.   private
  438.     FRounds: Integer;
  439.     FVersion: TSAFERVersion;
  440.     procedure SetRounds(Value: Integer);
  441.     procedure SetVersion(Value: TSAFERVersion);
  442.   protected
  443.     procedure DoInit(const Key; Size: Integer); override;
  444.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  445.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  446.   public
  447.     class function Context: TCipherContext; override;
  448.   published
  449.     property Rounds: Integer read FRounds write SetRounds;
  450.     property Version: TSAFERVersion read FVersion write SetVersion;
  451.   end;
  452.  
  453.   TCipher_Shark = class(TDECCipher)
  454.   protected
  455.     procedure DoInit(const Key; Size: Integer); override;
  456.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  457.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  458.   public
  459.     class function Context: TCipherContext; override;
  460.   end;
  461.  
  462.   TCipher_Skipjack = class(TDECCipher)
  463.   protected
  464.     procedure DoInit(const Key; Size: Integer); override;
  465.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  466.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  467.   public
  468.     class function Context: TCipherContext; override;
  469.   end;
  470.  
  471.   TCipher_TEA = class(TDECCipher) {Tiny Encryption Algorithm}
  472.   private
  473.     FRounds: Integer; {16 - 32, default 16 is sufficient, 32 is ample}
  474.     procedure SetRounds(Value: Integer);
  475.   protected
  476.     procedure DoInit(const Key; Size: Integer); override;
  477.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  478.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  479.   public
  480.     class function Context: TCipherContext; override;
  481.   published
  482.     property Rounds: Integer read FRounds write SetRounds;
  483.   end;
  484.  
  485.   TCipher_TEAN = class(TCipher_TEA) {Tiny Encryption Algorithm, extended Version}
  486.   protected
  487.     procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
  488.     procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
  489.   end;
  490.  
  491. function  ValidCipher(CipherClass: TDECCipherClass = nil): TDECCipherClass;
  492. function  CipherByName(const Name: String): TDECCipherClass;
  493. function  CipherByIdentity(Identity: LongWord): TDECCipherClass;
  494. procedure SetDefaultCipherClass(CipherClass: TDECCipherClass = nil);
  495.  
  496. var
  497.   StreamBufferSize: Integer = 8192;
  498.  
  499. implementation
  500.  
  501. uses TypInfo, DECData;
  502.  
  503. resourcestring
  504.   sAlreadyPadded        = 'Cipher have already padded, can not process message';
  505.   sInvalidState         = 'Cipher is not in valid state for this action';
  506.   sInvalidMessageLength = 'Messagelength for %s must be a multiple of %d bytes';
  507.   sKeyMaterialToLarge   = 'Keymaterial is to large as can be used, security issue';
  508.   sIVMaterialToLarge    = 'Initvector is to large as can be used, security issue';
  509.   sInvalidMACMode       = 'Invalid Cipher mode to compute MAC';
  510.   sCipherNoDefault      = 'No default cipher are registered';
  511.  
  512. var
  513.   FDefaultCipherClass: TDECCipherClass = nil;
  514.  
  515. function ValidCipher(CipherClass: TDECCipherClass): TDECCipherClass;
  516. begin
  517.   if CipherClass <> nil then Result := CipherClass
  518.     else Result := FDefaultCipherClass;
  519.   if Result = nil then raise EDECException.Create(sCipherNoDefault);
  520. end;
  521.  
  522. function CipherByName(const Name: String): TDECCipherClass;
  523. begin
  524.   Result := TDECCipherClass(DECClassByName(Name, TDECCipher));
  525. end;
  526.  
  527. function CipherByIdentity(Identity: LongWord): TDECCipherClass;
  528. begin
  529.   Result := TDECCipherClass(DECClassByIdentity(Identity, TDECCipher));
  530. end;
  531.  
  532. procedure SetDefaultCipherClass(CipherClass: TDECCipherClass);
  533. begin
  534.   if CipherClass <> nil then CipherClass.Register;
  535.   FDefaultCipherClass := CipherClass;
  536. end;
  537.  
  538. procedure TDECCipher.SetMode(Value: TCipherMode);
  539. begin
  540.   if Value <> FMode then
  541.   begin
  542.     if not (FState in [csNew, csInitialized, csDone]) then Done;
  543.     FMode := Value;
  544.   end;
  545. end;
  546.  
  547. procedure TDECCipher.CheckState(States: TCipherStates);
  548. var
  549.   S: String;
  550. begin
  551.   if not (FState in States) then
  552.   begin
  553.     if FState = csPadded then S := sAlreadyPadded
  554.       else S := sInvalidState;
  555.     raise EDECException.Create(S);
  556.   end;
  557. end;
  558.  
  559. constructor TDECCipher.Create;
  560. var
  561.   MustUserSaved: Boolean;
  562. begin
  563.   inherited Create;
  564.   with Context do
  565.   begin
  566.     FBufferSize := BufferSize;
  567.     FUserSize := UserSize;
  568.     MustUserSaved := UserSave;
  569.   end;
  570.   FDataSize := FBufferSize * 3 + FUserSize;
  571.   if MustUserSaved then Inc(FDataSize, FUserSize);
  572.   ReallocMem(FData, FDataSize);
  573.   FVector := @FData[0];
  574.   FFeedback := @FVector[FBufferSize];
  575.   FBuffer := @FFeedback[FBufferSize];
  576.   FUser := @FBuffer[FBufferSize];
  577.   if MustUserSaved then FUserSave := @PByteArray(FUser)[FUserSize]
  578.     else FUserSave := nil;
  579.   Protect;
  580. end;
  581.  
  582. destructor TDECCipher.Destroy;
  583. begin
  584.   Protect;
  585.   ReallocMem(FData, 0);
  586.   FVector := nil;
  587.   FFeedback := nil;
  588.   FBuffer := nil;
  589.   FUser := nil;
  590.   FUserSave := nil;
  591.   inherited Destroy;
  592. end;
  593.  
  594. procedure TDECCipher.Init(const Key; Size: Integer; const IVector; IVectorSize: Integer; IFiller: Byte);
  595. begin
  596.   Protect;
  597.  
  598.   if Size > Context.KeySize then
  599.     raise EDECException.Create(sKeyMaterialToLarge);
  600.   if IVectorSize > FBufferSize then
  601.     raise EDECException.Create(sIVMaterialToLarge);
  602.  
  603.   DoInit(Key, Size);
  604.   if FUserSave <> nil then
  605.     Move(FUser^, FUserSave^, FUserSize);
  606.  
  607.   FillChar(FVector^, FBufferSize, IFiller);
  608.   if IVectorSize = 0 then
  609.   begin
  610.     DoEncode(FVector, FVector, FBufferSize);
  611.     if FUserSave <> nil then Move(FUserSave^, FUser^, FUserSize);
  612.   end else Move(IVector, FVector^, IVectorSize);
  613.   Move(FVector^, FFeedback^, FBufferSize);
  614.   FState := csInitialized;
  615. end;
  616.  
  617. procedure TDECCipher.Init(const Key: Binary; const IVector: Binary; IFiller: Byte);
  618. begin
  619.   Init(Key[1], Length(Key), IVector[1], Length(IVector), IFiller);
  620. end;
  621.  
  622. procedure TDECCipher.Done;
  623. begin
  624.   if FState <> csDone then
  625.   begin
  626.     FState := csDone;
  627.     FBufferIndex := 0;
  628.     DoEncode(FFeedback, FBuffer, FBufferSize);
  629.     Move(FVector^, FFeedback^, FBufferSize);
  630.     if FUserSave <> nil then
  631.       Move(FUserSave^, FUser^, FUserSize);
  632.   end;
  633. end;
  634.  
  635. procedure TDECCipher.Protect;
  636. begin
  637.   FState := csNew;
  638.   ProtectBuffer(FData[0], FDataSize);
  639. end;
  640.  
  641. procedure InvalidMessageLength(Cipher: TDECCipher);
  642. begin
  643.   with Cipher do
  644.     raise EDECException.CreateFmt(sInvalidMessageLength,
  645.       [TypInfo.GetEnumName(TypeInfo(TCipherMode), Integer(FMode)), Context.BlockSize]);
  646. end;
  647.  
  648. procedure TDECCipher.Encode(const Source; var Dest; DataSize: Integer);
  649.  
  650.   procedure EncodeECBx(S,D: PByteArray; Size: Integer);
  651.   var
  652.     I: Integer;
  653.   begin
  654.     if Context.BlockSize = 1 then
  655.     begin
  656.       DoEncode(S, D, Size);
  657.       FState := csEncode;
  658.     end else
  659.     begin
  660.       Dec(Size, FBufferSize);
  661.       I := 0;
  662.       while I <= Size do
  663.       begin
  664.         DoEncode(@S[I], @D[I], FBufferSize);
  665.         Inc(I, FBufferSize);
  666.       end;
  667.       Dec(Size, I - FBufferSize);
  668.       if Size > 0 then
  669.         if Size mod Context.BlockSize = 0 then
  670.         begin
  671.           DoEncode(@S[I], @D[I], Size);
  672.           FState := csEncode;
  673.         end else
  674.         begin
  675.           FState := csPadded;
  676.           InvalidMessageLength(Self);
  677.         end;
  678.     end;
  679.   end;
  680.  
  681.   procedure EncodeCFB8(S,D: PByteArray; Size: Integer);
  682.   // CFB-8
  683.   var
  684.     I: Integer;
  685.   begin
  686.     I := 0;
  687.     while I < Size do
  688.     begin
  689.       DoEncode(FFeedback, FBuffer, FBufferSize);
  690.       Move(FFeedback[1], FFeedback[0], FBufferSize -1);
  691.       D[I] := S[I] xor FBuffer[0];
  692.       FFeedback[FBufferSize -1] := D[I];
  693.       Inc(I);
  694.     end;
  695.     FState := csEncode;
  696.   end;
  697.  
  698.   procedure EncodeOFB8(S,D: PByteArray; Size: Integer);
  699.   var
  700.     I: Integer;
  701.   begin
  702.     I := 0;
  703.     while I < Size do
  704.     begin
  705.       DoEncode(FFeedback, FBuffer, FBufferSize);
  706.       Move(FFeedback[1], FFeedback[0], FBufferSize -1);
  707.       FFeedback[FBufferSize -1] := FBuffer[0];
  708.       D[I] := S[I] xor FBuffer[0];
  709.       Inc(I);
  710.     end;
  711.     FState := csEncode;
  712.   end;
  713.  
  714.   procedure EncodeCFS8(S,D: PByteArray; Size: Integer);
  715.   // CFS-8, CTS as CFB
  716.   var
  717.     I: Integer;
  718.   begin
  719.     I := 0;
  720.     while I < Size do
  721.     begin
  722.       DoEncode(FFeedback, FBuffer, FBufferSize);
  723.       D[I] := S[I] xor FBuffer[0];
  724.       Move(FFeedback[1], FFeedback[0], FBufferSize -1);
  725.       FFeedback[FBufferSize -1] := FFeedback[FBufferSize -1] xor D[I];
  726.       Inc(I);
  727.     end;
  728.     FState := csEncode;
  729.   end;
  730.  
  731.   procedure EncodeCFBx(S,D: PByteArray; Size: Integer);
  732.   // CFB-BlockSize
  733.   var
  734.     I: Integer;
  735.     F: PByteArray;
  736.   begin
  737.     FState := csEncode;
  738.     if FBufferIndex > 0 then
  739.     begin
  740.       I := FBufferSize - FBufferIndex;
  741.       if I > Size then I := Size;
  742.       XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
  743.       Move(D[0], FFeedback[FBufferIndex], I);
  744.       Inc(FBufferIndex, I);
  745.       if FBufferIndex < FBufferSize then Exit;
  746.       Dec(Size, I);
  747.       S := @S[I];
  748.       D := @D[I];
  749.       FBufferIndex := 0
  750.     end;
  751.     Dec(Size, FBufferSize);
  752.     F := FFeedback;
  753.     I := 0;
  754.     while I < Size do
  755.     begin
  756.       DoEncode(F, FBuffer, FBufferSize);
  757.       XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
  758.       F := @D[I];
  759.       Inc(I, FBufferSize);
  760.     end;
  761.     if F <> FFeedback then
  762.       Move(F^, FFeedback^, FBufferSize);
  763.     Dec(Size, I - FBufferSize);
  764.     if Size > 0 then
  765.     begin
  766.       DoEncode(FFeedback, FBuffer, FBufferSize);
  767.       XORBuffers(S[I], FBuffer[0], Size, D[I]);
  768.       Move(D[I], FFeedback[0], Size);
  769.       FBufferIndex := Size;
  770.     end;
  771.   end;
  772.  
  773.   procedure EncodeOFBx(S,D: PByteArray; Size: Integer);
  774.   // OFB-BlockSize
  775.   var
  776.     I: Integer;
  777.   begin
  778.     FState := csEncode;
  779.     if FBufferIndex > 0 then
  780.     begin
  781.       I := FBufferSize - FBufferIndex;
  782.       if I > Size then I := Size;
  783.       XORBuffers(S[0], FFeedback[FBufferIndex], I, D[0]);
  784.       Inc(FBufferIndex, I);
  785.       if FBufferIndex < FBufferSize then Exit;
  786.       Dec(Size, I);
  787.       S := @S[I];
  788.       D := @D[I];
  789.       FBufferIndex := 0
  790.     end;
  791.     Dec(Size, FBufferSize);
  792.     I := 0;
  793.     while I < Size do
  794.     begin
  795.       DoEncode(FFeedback, FFeedback, FBufferSize);
  796.       XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]);
  797.       Inc(I, FBufferSize);
  798.     end;
  799.     Dec(Size, I - FBufferSize);
  800.     if Size > 0 then
  801.     begin
  802.       DoEncode(FFeedback, FFeedback, FBufferSize);
  803.       XORBuffers(S[I], FFeedback[0], Size, D[I]);
  804.       FBufferIndex := Size;
  805.     end;
  806.   end;
  807.  
  808.   procedure EncodeCFSx(S,D: PByteArray; Size: Integer);
  809.   // CFS-BlockSize
  810.   var
  811.     I: Integer;
  812.   begin
  813.     FState := csEncode;
  814.     if FBufferIndex > 0 then
  815.     begin
  816.       I := FBufferSize - FBufferIndex;
  817.       if I > Size then I := Size;
  818.       XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
  819.       XORBuffers(D[0], FFeedback[FBufferIndex], I, FFeedback[FBufferIndex]);
  820.       Inc(FBufferIndex, I);
  821.       if FBufferIndex < FBufferSize then Exit;
  822.       Dec(Size, I);
  823.       S := @S[I];
  824.       D := @D[I];
  825.       FBufferIndex := 0
  826.     end;
  827.     Dec(Size, FBufferSize);
  828.     I := 0;
  829.     while I < Size do
  830.     begin
  831.       DoEncode(FFeedback, FBuffer, FBufferSize);
  832.       XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
  833.       XORBuffers(D[I], FFeedback[0], FBufferSize, FFeedback[0]);
  834.       Inc(I, FBufferSize);
  835.     end;
  836.     Dec(Size, I - FBufferSize);
  837.     if Size > 0 then
  838.     begin
  839.       DoEncode(FFeedback, FBuffer, FBufferSize);
  840.       XORBuffers(S[I], FBuffer[0], Size, D[I]);
  841.       XORBuffers(D[I], FFeedback[0], Size, FFeedback[0]);
  842.       FBufferIndex := Size;
  843.     end;
  844.   end;
  845.  
  846.   procedure EncodeCBCx(S,D: PByteArray; Size: Integer);
  847.   var
  848.     F: PByteArray;
  849.     I: Integer;
  850.   begin
  851.     Dec(Size, FBufferSize);
  852.     F := FFeedback;
  853.     I := 0;
  854.     while I <= Size do
  855.     begin
  856.       XORBuffers(S[I], F[0], FBufferSize, D[I]);
  857.       F := @D[I];
  858.       DoEncode(F, F, FBufferSize);
  859.       Inc(I, FBufferSize);
  860.     end;
  861.     if F <> FFeedback then
  862.       Move(F[0], FFeedback[0], FBufferSize);
  863.     Dec(Size, I - FBufferSize);
  864.     if Size > 0 then
  865.     begin  // padding
  866.       EncodeCFB8(@S[I], @D[I], Size);
  867.       FState := csPadded;
  868.     end else FState := csEncode;
  869.   end;
  870.  
  871.   procedure EncodeCTSx(S,D: PByteArray; Size: Integer);
  872.   var
  873.     I: Integer;
  874.   begin
  875.     Dec(Size, FBufferSize);
  876.     I := 0;
  877.     while I <= Size do
  878.     begin
  879.       XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]);
  880.       DoEncode(@D[I], @D[I], FBufferSize);
  881.       XORBuffers(D[I], FFeedback[0], FBufferSize, FFeedback[0]);
  882.       Inc(I, FBufferSize);
  883.      end;
  884.      Dec(Size, I - FBufferSize);
  885.      if Size > 0 then
  886.      begin // padding
  887.        EncodeCFS8(@S[I], @D[I], Size);
  888.        FState := csPadded;
  889.      end else FState := csEncode;
  890.   end;
  891.  
  892. begin
  893.   CheckState([csInitialized, csEncode, csDone]);
  894.   case FMode of
  895.     cmECBx: EncodeECBx(@Source, @Dest, DataSize);
  896.     cmCBCx: EncodeCBCx(@Source, @Dest, DataSize);
  897.     cmCTSx: EncodeCTSx(@Source, @Dest, DataSize);
  898.     cmCFB8: EncodeCFB8(@Source, @Dest, DataSize);
  899.     cmCFBx: EncodeCFBx(@Source, @Dest, DataSize);
  900.     cmOFB8: EncodeOFB8(@Source, @Dest, DataSize);
  901.     cmOFBx: EncodeOFBx(@Source, @Dest, DataSize);
  902.     cmCFS8: EncodeCFS8(@Source, @Dest, DataSize);
  903.     cmCFSx: EncodeCFSx(@Source, @Dest, DataSize);
  904.   end;
  905. end;
  906.  
  907. procedure TDECCipher.Decode(const Source; var Dest; DataSize: Integer);
  908.  
  909.   procedure DecodeECBx(S,D: PByteArray; Size: Integer);
  910.   var
  911.     I: Integer;
  912.   begin
  913.     if Context.BlockSize = 1 then
  914.     begin
  915.       DoDecode(S, D, Size);
  916.       FState := csDecode;
  917.     end else
  918.     begin
  919.       Dec(Size, FBufferSize);
  920.       I := 0;
  921.       while I <= Size do
  922.       begin
  923.         DoDecode(@S[I], @D[I], FBufferSize);
  924.         Inc(I, FBufferSize);
  925.       end;
  926.       Dec(Size, I - FBufferSize);
  927.       if Size > 0 then
  928.         if Size mod Context.BlockSize = 0 then
  929.         begin
  930.           DoDecode(@S[I], @D[I], Size);
  931.           FState := csDecode;
  932.         end else
  933.         begin
  934.           FState := csPadded;
  935.           InvalidMessageLength(Self);
  936.         end;
  937.     end;
  938.   end;
  939.  
  940.   procedure DecodeCFB8(S,D: PByteArray; Size: Integer);
  941.   // CFB-8
  942.   var
  943.     I: Integer;
  944.   begin
  945.     I := 0;
  946.     while I < Size do
  947.     begin
  948.       DoEncode(FFeedback, FBuffer, FBufferSize);
  949.       Move(FFeedback[1], FFeedback[0], FBufferSize -1);
  950.       FFeedback[FBufferSize -1] := S[I];
  951.       D[I] := S[I] xor FBuffer[0];
  952.       Inc(I);
  953.     end;
  954.     FState := csDecode;
  955.   end;
  956.  
  957.   procedure DecodeOFB8(S,D: PByteArray; Size: Integer);
  958.   // same as EncodeOFB
  959.   var
  960.     I: Integer;
  961.   begin
  962.     I := 0;
  963.     while I < Size do
  964.     begin
  965.       DoEncode(FFeedback, FBuffer, FBufferSize);
  966.       Move(FFeedback[1], FFeedback[0], FBufferSize -1);
  967.       FFeedback[FBufferSize -1] := FBuffer[0];
  968.       D[I] := S[I] xor FBuffer[0];
  969.       Inc(I);
  970.     end;
  971.     FState := csDecode;
  972.   end;
  973.  
  974.   procedure DecodeCFS8(S,D: PByteArray; Size: Integer);
  975.   var
  976.     I: Integer;
  977.   begin
  978.     I := 0;
  979.     while I < Size do
  980.     begin
  981.       DoEncode(FFeedback, FBuffer, FBufferSize);
  982.       Move(FFeedback[1], FFeedback[0], FBufferSize -1);
  983.       FFeedback[FBufferSize -1] := FFeedback[FBufferSize -1] xor S[I];
  984.       D[I] := S[I] xor FBuffer[0];
  985.       Inc(I);
  986.     end;
  987.     FState := csDecode;
  988.   end;
  989.  
  990.   procedure DecodeCFBx(S,D: PByteArray; Size: Integer);
  991.   // CFB-BlockSize
  992.   var
  993.     I: Integer;
  994.     F: PByteArray;
  995.   begin
  996.     FState := csDecode;
  997.     if FBufferIndex > 0 then
  998.     begin // remain bytes of last decode
  999.       I := FBufferSize - FBufferIndex;
  1000.       if I > Size then I := Size;
  1001.       Move(S[0], FFeedback[FBufferIndex], I);
  1002.       XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
  1003.       Inc(FBufferIndex, I);
  1004.       if FBufferIndex < FBufferSize then Exit;
  1005.       Dec(Size, I);
  1006.       S := @S[I];
  1007.       D := @D[I];
  1008.       FBufferIndex := 0
  1009.     end;
  1010.   // process chunks of FBufferSize bytes
  1011.     Dec(Size, FBufferSize);
  1012.     I := 0;
  1013.     if S <> D then
  1014.     begin
  1015.       F := FFeedback;
  1016.       while I < Size do
  1017.       begin
  1018.         DoEncode(F, FBuffer, FBufferSize);
  1019.         XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
  1020.         F := @S[I];
  1021.         Inc(I, FBufferSize);
  1022.       end;
  1023.       if F <> FFeedback then
  1024.         Move(F^, FFeedback^, FBufferSize);
  1025.     end else
  1026.       while I < Size do
  1027.       begin
  1028.         DoEncode(FFeedback, FBuffer, FBufferSize);
  1029.         Move(S[I], FFeedback[0], FBufferSize);
  1030.         XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
  1031.         Inc(I, FBufferSize);
  1032.       end;
  1033.     Dec(Size, I - FBufferSize);
  1034.     if Size > 0 then
  1035.     begin // remain bytes
  1036.       DoEncode(FFeedback, FBuffer, FBufferSize);
  1037.       Move(S[I], FFeedback[0], Size);
  1038.       XORBuffers(S[I], FBuffer[0], Size, D[I]);
  1039.       FBufferIndex := Size;
  1040.     end;
  1041.   end;
  1042.  
  1043.   procedure DecodeOFBx(S,D: PByteArray; Size: Integer);
  1044.   // OFB-BlockSize, same as EncodeOFBx
  1045.   var
  1046.     I: Integer;
  1047.   begin
  1048.     FState := csDecode;
  1049.     if FBufferIndex > 0 then
  1050.     begin
  1051.       I := FBufferSize - FBufferIndex;
  1052.       if I > Size then I := Size;
  1053.       XORBuffers(S[0], FFeedback[FBufferIndex], I, D[0]);
  1054.       Inc(FBufferIndex, I);
  1055.       if FBufferIndex < FBufferSize then Exit;
  1056.       Dec(Size, I);
  1057.       S := @S[I];
  1058.       D := @D[I];
  1059.       FBufferIndex := 0
  1060.     end;
  1061.     Dec(Size, FBufferSize);
  1062.     I := 0;
  1063.     while I < Size do
  1064.     begin
  1065.       DoEncode(FFeedback, FFeedback, FBufferSize);
  1066.       XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]);
  1067.       Inc(I, FBufferSize);
  1068.     end;
  1069.     Dec(Size, I - FBufferSize);
  1070.     if Size > 0 then
  1071.     begin
  1072.       DoEncode(FFeedback, FFeedback, FBufferSize);
  1073.       XORBuffers(S[I], FFeedback[0], Size, D[I]);
  1074.       FBufferIndex := Size;
  1075.     end;
  1076.   end;
  1077.  
  1078.   procedure DecodeCFSx(S,D: PByteArray; Size: Integer);
  1079.   // CFS-BlockSize
  1080.   var
  1081.     I: Integer;
  1082.   begin
  1083.     FState := csDecode;
  1084.     if FBufferIndex > 0 then
  1085.     begin // remain bytes of last decode
  1086.       I := FBufferSize - FBufferIndex;
  1087.       if I > Size then I := Size;
  1088.       XORBuffers(S[0], FFeedback[FBufferIndex], I, FFeedback[FBufferIndex]);
  1089.       XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
  1090.       Inc(FBufferIndex, I);
  1091.       if FBufferIndex < FBufferSize then Exit;
  1092.       Dec(Size, I);
  1093.       S := @S[I];
  1094.       D := @D[I];
  1095.       FBufferIndex := 0
  1096.     end;
  1097.   // process chunks of FBufferSize bytes
  1098.     Dec(Size, FBufferSize);
  1099.     I := 0;
  1100.     while I < Size do
  1101.     begin
  1102.       DoEncode(FFeedback, FBuffer, FBufferSize);
  1103.       XORBuffers(S[I], FFeedback[0], FBufferSize, FFeedback[0]);
  1104.       XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
  1105.       Inc(I, FBufferSize);
  1106.     end;
  1107.     Dec(Size, I - FBufferSize);
  1108.     if Size > 0 then
  1109.     begin // remain bytes
  1110.       DoEncode(FFeedback, FBuffer, FBufferSize);
  1111.       XORBuffers(S[I], FFeedback[0], Size, FFeedback[0]);
  1112.       XORBuffers(S[I], FBuffer[0], Size, D[I]);
  1113.       FBufferIndex := Size;
  1114.     end;
  1115.   end;
  1116.  
  1117.   procedure DecodeCBCx(S,D: PByteArray; Size: Integer);
  1118.   var
  1119.     I: Integer;
  1120.     F,B,T: PByteArray;
  1121.   begin
  1122.     Dec(Size, FBufferSize);
  1123.     F := FFeedback;
  1124.     I := 0;
  1125.     if S = D then
  1126.     begin
  1127.       B := FBuffer;
  1128.       while I <= Size do
  1129.       begin
  1130.         Move(S[I], B[0], FBufferSize);
  1131.         DoDecode(@S[I], @S[I], FBufferSize);
  1132.         XORBuffers(S[I], F[0], FBufferSize, S[I]);
  1133.         T := F;
  1134.         F := B;
  1135.         B := T;
  1136.         Inc(I, FBufferSize);
  1137.       end;
  1138.     end else
  1139.       while I <= Size do
  1140.       begin
  1141.         DoDecode(@S[I], @D[I], FBufferSize);
  1142.         XORBuffers(F[0], D[I], FBufferSize, D[I]);
  1143.         F := @S[I];
  1144.         Inc(I, FBufferSize);
  1145.       end;
  1146.     if F <> FFeedback then
  1147.       Move(F[0], FFeedback[0], FBufferSize);
  1148.     Dec(Size, I - FBufferSize);
  1149.     if Size > 0 then
  1150.     begin
  1151.       DecodeCFB8(@S[I], @D[I], Size);
  1152.       FState := csPadded;
  1153.     end else FState := csDecode;
  1154.   end;
  1155.  
  1156.   procedure DecodeCTSx(S,D: PByteArray; Size: Integer);
  1157.   var
  1158.     I: Integer;
  1159.     F,B,T: PByteArray;
  1160.   begin
  1161.     Dec(Size, FBufferSize);
  1162.     F := FFeedback;
  1163.     B := FBuffer;
  1164.     I := 0;
  1165.     while I <= Size do
  1166.     begin
  1167.       XORBuffers(S[I], F[0], FBufferSize, B[0]);
  1168.       DoDecode(@S[I], @D[I], FBufferSize);
  1169.       XORBuffers(D[I], F[0], FBufferSize, D[I]);
  1170.       T := B;
  1171.       B := F;
  1172.       F := T;
  1173.       Inc(I, FBufferSize);
  1174.     end;
  1175.     if F <> FFeedback then
  1176.       Move(F[0], FFeedback[0], FBufferSize);
  1177.     Dec(Size, I - FBufferSize);
  1178.     if Size > 0 then
  1179.     begin
  1180.       DecodeCFS8(@S[I], @D[I], Size);
  1181.       FState := csPadded;
  1182.     end else FState := csDecode;
  1183.   end;
  1184.  
  1185. begin
  1186.   CheckState([csInitialized, csDecode, csDone]);
  1187.   case FMode of
  1188.     cmECBx: DecodeECBx(@Source, @Dest, DataSize);
  1189.     cmCBCx: DecodeCBCx(@Source, @Dest, DataSize);
  1190.     cmCTSx: DecodeCTSx(@Source, @Dest, DataSize);
  1191.     cmCFB8: DecodeCFB8(@Source, @Dest, DataSize);
  1192.     cmCFBx: DecodeCFBx(@Source, @Dest, DataSize);
  1193.     cmOFB8: DecodeOFB8(@Source, @Dest, DataSize);
  1194.     cmOFBx: DecodeOFBx(@Source, @Dest, DataSize);
  1195.     cmCFS8: DecodeCFS8(@Source, @Dest, DataSize);
  1196.     cmCFSx: DecodeCFSx(@Source, @Dest, DataSize);
  1197.   end;
  1198. end;
  1199.  
  1200. function TDECCipher.EncodeBinary(const Source: Binary; Format: TDECFormatClass): Binary;
  1201. begin
  1202.   SetLength(Result, Length(Source));
  1203.   Encode(Source[1], Result[1], Length(Source));
  1204.   Result := ValidFormat(Format).Encode(Result);
  1205. end;
  1206.  
  1207. function TDECCipher.DecodeBinary(const Source: Binary; Format: TDECFormatClass): Binary;
  1208. begin
  1209.   Result := ValidFormat(Format).Decode(Source);
  1210.   Decode(Result[1], Result[1], Length(Result));
  1211. end;
  1212.  
  1213. procedure DoCodeStream(Source,Dest: TStream; Size: Int64; BlockSize: Integer; const Proc: TDECCipherCodeEvent; const Progress: IDECProgress);
  1214. var
  1215.   Buffer: Binary;
  1216.   BufferSize,Bytes: Integer;
  1217.   Min,Max,Pos: Int64;
  1218. begin
  1219.   Pos := Source.Position;
  1220.   if Size < 0 then Size := Source.Size - Pos;
  1221.   Min := Pos;
  1222.   Max := Pos + Size;
  1223.   if Size > 0 then
  1224.   try
  1225.     if StreamBufferSize <= 0 then StreamBufferSize := 8192;
  1226.     BufferSize := StreamBufferSize mod BlockSize;
  1227.     if BufferSize = 0 then BufferSize := StreamBufferSize
  1228.       else BufferSize := StreamBufferSize + BlockSize - BufferSize;
  1229.     if Size > BufferSize then SetLength(Buffer, BufferSize)
  1230.       else SetLength(Buffer, Size);
  1231.     while Size > 0 do
  1232.     begin
  1233.       if Assigned(Progress) then Progress.Process(Min, Max, Pos);
  1234.       Bytes := BufferSize;
  1235.       if Bytes > Size then Bytes := Size;
  1236.       Source.ReadBuffer(Buffer[1], Bytes);
  1237.       Proc(Buffer[1], Buffer[1], Bytes);
  1238.       Dest.WriteBuffer(Buffer[1], Bytes);
  1239.       Dec(Size, Bytes);
  1240.       Inc(Pos, Bytes);
  1241.     end;
  1242.   finally
  1243.     ProtectBinary(Buffer);
  1244.     if Assigned(Progress) then Progress.Process(Min, Max, Max);
  1245.   end;
  1246. end;
  1247.  
  1248. procedure DoCodeFile(const Source,Dest: String; BlockSize: Integer; const Proc: TDECCipherCodeEvent; const Progress: IDECProgress);
  1249. var
  1250.   S,D: TStream;
  1251. begin
  1252.   S := TFileStream.Create(Source, fmOpenRead or fmShareDenyNone);
  1253.   try
  1254.     D := TFileStream.Create(Dest, fmCreate);
  1255.     try
  1256.       DoCodeStream(S, D, S.Size, BlockSize, Proc, Progress);
  1257.     finally
  1258.       D.Free;
  1259.     end;
  1260.   finally
  1261.     S.Free;
  1262.   end;
  1263. end;
  1264.  
  1265. procedure TDECCipher.EncodeFile(const Source, Dest: String; const Progress: IDECProgress);
  1266. begin
  1267.   DoCodeFile(Source, Dest, Context.BlockSize, Encode, Progress);
  1268. end;
  1269.  
  1270. procedure TDECCipher.DecodeFile(const Source, Dest: String; const Progress: IDECProgress);
  1271. begin
  1272.   DoCodeFile(Source, Dest, Context.BlockSize, Decode, Progress);
  1273. end;
  1274.  
  1275. procedure TDECCipher.EncodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress);
  1276. begin
  1277.   DoCodeStream(Source, Dest, DataSize, Context.BlockSize, Encode, Progress);
  1278. end;
  1279.  
  1280. procedure TDECCipher.DecodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress);
  1281. begin
  1282.   DoCodeStream(Source, Dest, DataSize, Context.BlockSize, Decode, Progress);
  1283. end;
  1284.  
  1285. function TDECCipher.CalcMAC(Format: TDECFormatClass): Binary;
  1286. begin
  1287.   Done;
  1288.   if FMode in [cmECBx] then raise EDECException.Create(sInvalidMACMode)
  1289.     else Result := ValidFormat(Format).Encode(FBuffer^, FBufferSize);
  1290. end;
  1291.  
  1292. // .TCipher_Null
  1293. class function TCipher_Null.Context: TCipherContext;
  1294. begin
  1295.   Result.KeySize := 0;
  1296.   Result.BlockSize := 1;
  1297.   Result.BufferSize := 32;
  1298.   Result.UserSize := 0;
  1299.   Result.UserSave := False;
  1300. end;
  1301.  
  1302. procedure TCipher_Null.DoInit(const Key; Size: Integer);
  1303. begin
  1304. end;
  1305.  
  1306. procedure TCipher_Null.DoEncode(Source, Dest: Pointer; Size: Integer);
  1307. begin
  1308.   if Source <> Dest then Move(Source^, Dest^, Size);
  1309. end;
  1310.  
  1311. procedure TCipher_Null.DoDecode(Source, Dest: Pointer; Size: Integer);
  1312. begin
  1313.   if Source <> Dest then Move(Source^, Dest^, Size);
  1314. end;
  1315.  
  1316. // .TCipher_Blowfish
  1317.  
  1318. {$IFDEF UseASM}
  1319.   {$IFDEF 486GE}
  1320.     {$DEFINE Blowfish_asm}
  1321.   {$ENDIF}
  1322. {$ENDIF}
  1323.  
  1324. type
  1325.   PBlowfish = ^TBlowfish;
  1326.   TBlowfish = array[0..3, 0..255] of LongWord;
  1327.  
  1328. class function TCipher_Blowfish.Context: TCipherContext;
  1329. begin
  1330.   Result.KeySize := 56;
  1331.   Result.BufferSize := 8;
  1332.   Result.BlockSize := 8;
  1333.   Result.UserSize := SizeOf(Blowfish_Data) + SizeOf(Blowfish_Key);
  1334.   Result.UserSave := False;
  1335. end;
  1336.  
  1337. procedure TCipher_Blowfish.DoInit(const Key; Size: Integer);
  1338. var
  1339.   I,J: Integer;
  1340.   B: array[0..1] of LongWord;
  1341.   K: PByteArray;
  1342.   P: PLongArray;
  1343.   S: PBlowfish;
  1344. begin
  1345.   K := @Key;
  1346.   S := FUser;
  1347.   P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data));
  1348.   Move(Blowfish_Data, S^, SizeOf(Blowfish_Data));
  1349.   Move(Blowfish_Key, P^, Sizeof(Blowfish_Key));
  1350.   J := 0;
  1351.   if Size > 0 then
  1352.     for I := 0 to 17 do
  1353.     begin
  1354.       P[I] := P[I] xor (K[(J + 0) mod Size] shl 24 +
  1355.                         K[(J + 1) mod Size] shl 16 +
  1356.                         K[(J + 2) mod Size] shl  8 +
  1357.                         K[(J + 3) mod Size] shl  0);
  1358.       J := (J + 4) mod Size;
  1359.     end;
  1360.   FillChar(B, SizeOf(B), 0);
  1361.   for I := 0 to 8 do
  1362.   begin
  1363.     DoEncode(@B, @B, SizeOf(B));
  1364.     P[I * 2 + 0] := SwapLong(B[0]);
  1365.     P[I * 2 + 1] := SwapLong(B[1]);
  1366.   end;
  1367.   for I := 0 to 3 do
  1368.     for J := 0 to 127 do
  1369.     begin
  1370.       DoEncode(@B, @B, SizeOf(B));
  1371.       S[I, J * 2 + 0] := SwapLong(B[0]);
  1372.       S[I, J * 2 + 1] := SwapLong(B[1]);
  1373.     end;
  1374.   FillChar(B, SizeOf(B), 0);
  1375. end;
  1376.  
  1377. procedure TCipher_Blowfish.DoEncode(Source, Dest: Pointer; Size: Integer);
  1378. {$IFDEF Blowfish_asm}  // specialy for CPU >= 486
  1379. // Source = EDX, Dest=ECX, Size on Stack
  1380. asm
  1381.         PUSH   EDI
  1382.         PUSH   ESI
  1383.         PUSH   EBX
  1384.         PUSH   EBP
  1385.         PUSH   ECX
  1386.         MOV    ESI,[EAX].TCipher_Blowfish.FUser
  1387.         MOV    EBX,[EDX + 0]     // A
  1388.         MOV    EBP,[EDX + 4]     // B
  1389.         BSWAP  EBX               // CPU >= 486
  1390.         BSWAP  EBP
  1391.         XOR    EBX,[ESI + 4 * 256 * 4]
  1392.         XOR    EDI,EDI
  1393. @@1:    MOV    EAX,EBX
  1394.         SHR    EBX,16
  1395.         MOVZX  ECX,BH
  1396.         AND    EBX,0FFh
  1397.         MOV    ECX,[ESI + ECX * 4 + 1024 * 0]
  1398.         MOV    EBX,[ESI + EBX * 4 + 1024 * 1]
  1399.         MOVZX  EDX,AH
  1400.         ADD    EBX,ECX
  1401.         MOVZX  ECX,AL
  1402.         MOV    EDX,[ESI + EDX * 4 + 1024 * 2]
  1403.         MOV    ECX,[ESI + ECX * 4 + 1024 * 3]
  1404.         XOR    EBX,EDX
  1405.         XOR    EBP,[ESI + 4 * 256 * 4 + 4 + EDI * 4]
  1406.         ADD    EBX,ECX
  1407.         INC    EDI
  1408.         XOR    EBX,EBP
  1409.         TEST   EDI,010h
  1410.         MOV    EBP,EAX
  1411.         JZ     @@1
  1412.         POP    EAX
  1413.         XOR    EBP,[ESI + 4 * 256 * 4 + 17 * 4]
  1414.         BSWAP  EBX
  1415.         BSWAP  EBP
  1416.         MOV    [EAX + 4],EBX
  1417.         MOV    [EAX + 0],EBP
  1418.         POP    EBP
  1419.         POP    EBX
  1420.         POP    ESI
  1421.         POP    EDI
  1422. end;
  1423. {$ELSE}
  1424. var
  1425.   I,A,B: LongWord;
  1426.   P: PLongArray;
  1427.   D: PBlowfish;
  1428. begin
  1429.   Assert(Size = Context.BlockSize);
  1430.  
  1431.   D := FUser;
  1432.   P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data));
  1433.   A := SwapLong(PLongArray(Source)[0]) xor P[0]; P := @P[1];
  1434.   B := SwapLong(PLongArray(Source)[1]);
  1435.   for I := 0 to 7 do
  1436.   begin
  1437.     B := B xor P[0] xor (D[0, A shr 24        ] +
  1438.                          D[1, A shr 16 and $FF] xor
  1439.                          D[2, A shr  8 and $FF] +
  1440.                          D[3, A        and $FF]);
  1441.  
  1442.     A := A xor P[1] xor (D[0, B shr 24        ] +
  1443.                          D[1, B shr 16 and $FF] xor
  1444.                          D[2, B shr  8 and $FF] +
  1445.                          D[3, B        and $FF]);
  1446.     P := @P[2];
  1447.   end;
  1448.   PLongArray(Dest)[0] := SwapLong(B xor P[0]);
  1449.   PLongArray(Dest)[1] := SwapLong(A);
  1450. end;
  1451. {$ENDIF}
  1452.  
  1453. procedure TCipher_Blowfish.DoDecode(Source, Dest: Pointer; Size: Integer);
  1454. {$IFDEF Blowfish_asm}
  1455. asm
  1456.         PUSH   EDI
  1457.         PUSH   ESI
  1458.         PUSH   EBX
  1459.         PUSH   EBP
  1460.         PUSH   ECX
  1461.         MOV    ESI,[EAX].TCipher_Blowfish.FUser
  1462.         MOV    EBX,[EDX + 0]     // A
  1463.         MOV    EBP,[EDX + 4]     // B
  1464.         BSWAP  EBX
  1465.         BSWAP  EBP
  1466.         XOR    EBX,[ESI + 4 * 256 * 4 + 17 * 4]
  1467.         MOV    EDI,16
  1468. @@1:    MOV    EAX,EBX
  1469.         SHR    EBX,16
  1470.         MOVZX  ECX,BH
  1471.         MOVZX  EDX,BL
  1472.         MOV    EBX,[ESI + ECX * 4 + 1024 * 0]
  1473.         MOV    EDX,[ESI + EDX * 4 + 1024 * 1]
  1474.         MOVZX  ECX,AH
  1475.         LEA    EBX,[EBX + EDX]
  1476.         MOVZX  EDX,AL
  1477.         MOV    ECX,[ESI + ECX * 4 + 1024 * 2]
  1478.         MOV    EDX,[ESI + EDX * 4 + 1024 * 3]
  1479.         XOR    EBX,ECX
  1480.         XOR    EBP,[ESI + 4 * 256 * 4 + EDI * 4]
  1481.         LEA    EBX,[EBX + EDX]
  1482.         XOR    EBX,EBP
  1483.         DEC    EDI
  1484.         MOV    EBP,EAX
  1485.         JNZ    @@1
  1486.         POP    EAX
  1487.         XOR    EBP,[ESI + 4 * 256 * 4]
  1488.         BSWAP  EBX
  1489.         BSWAP  EBP
  1490.         MOV    [EAX + 0],EBP
  1491.         MOV    [EAX + 4],EBX
  1492.         POP    EBP
  1493.         POP    EBX
  1494.         POP    ESI
  1495.         POP    EDI
  1496. end;
  1497. {$ELSE}
  1498. var
  1499.   I,A,B: LongWord;
  1500.   P: PLongArray;
  1501.   D: PBlowfish;
  1502. begin
  1503.   Assert(Size = Context.BlockSize);
  1504.  
  1505.   D := FUser;
  1506.   P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data) + SizeOf(Blowfish_Key) - SizeOf(Integer));
  1507.   A := SwapLong(PLongArray(Source)[0]) xor P[0];
  1508.   B := SwapLong(PLongArray(Source)[1]);
  1509.   for I := 0 to 7 do
  1510.   begin
  1511.     Dec(PLongWord(P), 2);
  1512.     B := B xor P[1] xor (D[0, A shr 24        ] +
  1513.                          D[1, A shr 16 and $FF] xor
  1514.                          D[2, A shr  8 and $FF] +
  1515.                          D[3, A        and $FF]);
  1516.     A := A xor P[0] xor (D[0, B shr 24        ] +
  1517.                          D[1, B shr 16 and $FF] xor
  1518.                          D[2, B shr  8 and $FF] +
  1519.                          D[3, B        and $FF]);
  1520.   end;
  1521.   Dec(PLongWord(P));
  1522.   PLongArray(Dest)[0] := SwapLong(B xor P[0]);
  1523.   PLongArray(Dest)[1] := SwapLong(A);
  1524. end;
  1525. {$ENDIF}
  1526.  
  1527. // .TCipher_Twofish
  1528. type
  1529.   PTwofishBox = ^TTwofishBox;
  1530.   TTwofishBox = array[0..3, 0..255] of Longword;
  1531.  
  1532.   TLongRec = record
  1533.                case Integer of
  1534.                  0: (L: Longword);
  1535.                  1: (A,B,C,D: Byte);
  1536.              end;
  1537.  
  1538. class function TCipher_Twofish.Context: TCipherContext;
  1539. begin
  1540.   Result.KeySize := 32;
  1541.   Result.BufferSize := 16;
  1542.   Result.BlockSize := 16;
  1543.   Result.UserSize := 4256;
  1544.   Result.UserSave := False;
  1545. end;
  1546.  
  1547. procedure TCipher_Twofish.DoInit(const Key; Size: Integer);
  1548. var
  1549.   BoxKey: array[0..3] of TLongRec;
  1550.   SubKey: PLongArray;
  1551.   Box: PTwofishBox;
  1552.  
  1553.   procedure SetupKey;
  1554.  
  1555.     function Encode(K0, K1: Integer): Integer;
  1556.     var
  1557.       R, I, J, G2, G3: Integer;
  1558.       B: byte;
  1559.     begin
  1560.       R := 0;
  1561.       for I := 0 to 1 do
  1562.       begin
  1563.         if I <> 0 then R := R xor K0 else R := R xor K1;
  1564.         for J := 0 to 3 do
  1565.         begin
  1566.           B := R shr 24;
  1567.           if B and $80 <> 0 then G2 := (B shl 1 xor $014D) and $FF
  1568.             else G2 := B shl 1 and $FF;
  1569.           if B and 1 <> 0 then G3 := (B shr 1 and $7F) xor $014D shr 1 xor G2
  1570.             else G3 := (B shr 1 and $7F) xor G2;
  1571.           R := R shl 8 xor G3 shl 24 xor G2 shl 16 xor G3 shl 8 xor B;
  1572.         end;
  1573.       end;
  1574.       Result := R;
  1575.     end;
  1576.  
  1577.     function F32(X: Integer; K: array of Integer): Integer;
  1578.     var
  1579.       A, B, C, D: LongWord;
  1580.     begin
  1581.       A := X        and $FF;
  1582.       B := X shr  8 and $FF;
  1583.       C := X shr 16 and $FF;
  1584.       D := X shr 24;
  1585.       if Size = 32 then
  1586.       begin
  1587.         A := Twofish_8x8[1, A] xor K[3]        and $FF;
  1588.         B := Twofish_8x8[0, B] xor K[3] shr  8 and $FF;
  1589.         C := Twofish_8x8[0, C] xor K[3] shr 16 and $FF;
  1590.         D := Twofish_8x8[1, D] xor K[3] shr 24;
  1591.       end;
  1592.       if Size >= 24 then
  1593.       begin
  1594.         A := Twofish_8x8[1, A] xor K[2]        and $FF;
  1595.         B := Twofish_8x8[1, B] xor K[2] shr  8 and $FF;
  1596.         C := Twofish_8x8[0, C] xor K[2] shr 16 and $FF;
  1597.         D := Twofish_8x8[0, D] xor K[2] shr 24;
  1598.       end;
  1599.       A := Twofish_8x8[0, A] xor K[1]        and $FF;
  1600.       B := Twofish_8x8[1, B] xor K[1] shr  8 and $FF;
  1601.       C := Twofish_8x8[0, C] xor K[1] shr 16 and $FF;
  1602.       D := Twofish_8x8[1, D] xor K[1] shr 24;
  1603.  
  1604.       A := Twofish_8x8[0, A] xor K[0]        and $FF;
  1605.       B := Twofish_8x8[0, B] xor K[0] shr  8 and $FF;
  1606.       C := Twofish_8x8[1, C] xor K[0] shr 16 and $FF;
  1607.       D := Twofish_8x8[1, D] xor K[0] shr 24;
  1608.  
  1609.       Result := Twofish_Data[0, A] xor Twofish_Data[1, B] xor
  1610.                 Twofish_Data[2, C] xor Twofish_Data[3, D];
  1611.     end;
  1612.  
  1613.   var
  1614.     I,J,A,B: Integer;
  1615.     E,O: array[0..3] of Integer;
  1616.     K: array[0..7] of Integer;
  1617.   begin
  1618.     FillChar(K, SizeOf(K), 0);
  1619.     Move(Key, K, Size);
  1620.     if Size <= 16 then Size := 16 else
  1621.       if Size <= 24 then Size := 24
  1622.         else Size := 32;
  1623.     J := Size shr 3 - 1;
  1624.     for I := 0 to J do
  1625.     begin
  1626.       E[I] := K[I shl 1];
  1627.       O[I] := K[I shl 1 + 1];
  1628.       BoxKey[J].L := Encode(E[I], O[I]);
  1629.       Dec(J);
  1630.     end;
  1631.     J := 0;
  1632.     for I := 0 to 19 do
  1633.     begin
  1634.       A := F32(J, E);
  1635.       B := F32(J + $01010101, O);
  1636.       B := B shl 8 or B shr 24;
  1637.       SubKey[I shl 1] := A + B;
  1638.       B := A + B shl 1;     // here buggy instead shr 1 it's correct shl 1
  1639.       SubKey[I shl 1 + 1] := B shl 9 or B shr 23;
  1640.       Inc(J, $02020202);
  1641.     end;
  1642.   end;
  1643.  
  1644.   procedure DoXOR(D, S: PLongArray; Value: LongWord);
  1645.   var
  1646.     I: LongWord;
  1647.   begin
  1648.     Value := (Value and $FF) * $01010101;
  1649.     for I := 0 to 63 do D[I] := S[I] xor Value;
  1650.   end;
  1651.  
  1652.   procedure SetupBox128;
  1653.   var
  1654.     L: array[0..255] of Byte;
  1655.     A,I: Integer;
  1656.   begin
  1657.     DoXOR(@L, @Twofish_8x8[0], BoxKey[1].L);
  1658.     A := BoxKey[0].A;
  1659.     for I := 0 to 255 do
  1660.       Box[0, I] := Twofish_Data[0, Twofish_8x8[0, L[I]] xor A];
  1661.     DoXOR(@L, @Twofish_8x8[1], BoxKey[1].L shr 8);
  1662.     A := BoxKey[0].B;
  1663.     for I := 0 to 255 do
  1664.       Box[1, I] := Twofish_Data[1, Twofish_8x8[0, L[I]] xor A];
  1665.     DoXOR(@L, @Twofish_8x8[0], BoxKey[1].L shr 16);
  1666.     A := BoxKey[0].C;
  1667.     for I := 0 to 255 do
  1668.       Box[2, I] := Twofish_Data[2, Twofish_8x8[1, L[I]] xor A];
  1669.     DoXOR(@L, @Twofish_8x8[1], BoxKey[1].L shr 24);
  1670.     A := BoxKey[0].D;
  1671.     for I := 0 to 255 do
  1672.       Box[3, I] := Twofish_Data[3, Twofish_8x8[1, L[I]] xor A];
  1673.   end;
  1674.  
  1675.   procedure SetupBox192;
  1676.   var
  1677.     L: array[0..255] of Byte;
  1678.     A,B,I: Integer;
  1679.   begin
  1680.     DoXOR(@L, @Twofish_8x8[1], BoxKey[2].L);
  1681.     A := BoxKey[0].A;
  1682.     B := BoxKey[1].A;
  1683.     for I := 0 to 255 do
  1684.       Box[0, I] := Twofish_Data[0, Twofish_8x8[0, Twofish_8x8[0, L[I]] xor B] xor A];
  1685.     DoXOR(@L, @Twofish_8x8[1], BoxKey[2].L shr 8);
  1686.     A := BoxKey[0].B;
  1687.     B := BoxKey[1].B;
  1688.     for I := 0 to 255 do
  1689.       Box[1, I] := Twofish_Data[1, Twofish_8x8[0, Twofish_8x8[1, L[I]] xor B] xor A];
  1690.     DoXOR(@L, @Twofish_8x8[0], BoxKey[2].L shr 16);
  1691.     A := BoxKey[0].C;
  1692.     B := BoxKey[1].C;
  1693.     for I := 0 to 255 do
  1694.       Box[2, I] := Twofish_Data[2, Twofish_8x8[1, Twofish_8x8[0, L[I]] xor B] xor A];
  1695.     DoXOR(@L ,@Twofish_8x8[0], BoxKey[2].L shr 24);
  1696.     A := BoxKey[0].D;
  1697.     B := BoxKey[1].D;
  1698.     for I := 0 to 255 do
  1699.       Box[3, I] := Twofish_Data[3, Twofish_8x8[1, Twofish_8x8[1, L[I]] xor B] xor A];
  1700.   end;
  1701.  
  1702.   procedure SetupBox256;
  1703.   var
  1704.     L: array[0..255] of Byte;
  1705.     K: array[0..255] of Byte;
  1706.     A,B,I: Integer;
  1707.   begin
  1708.     DoXOR(@K, @Twofish_8x8[1], BoxKey[3].L);
  1709.     for I := 0 to 255 do L[I] := Twofish_8x8[1, K[I]];
  1710.     DoXOR(@L, @L, BoxKey[2].L);
  1711.     A := BoxKey[0].A;
  1712.     B := BoxKey[1].A;
  1713.     for I := 0 to 255 do
  1714.       Box[0, I] := Twofish_Data[0, Twofish_8x8[0, Twofish_8x8[0, L[I]] xor B] xor A];
  1715.     DoXOR(@K, @Twofish_8x8[0], BoxKey[3].L shr 8);
  1716.     for I := 0 to 255 do L[I] := Twofish_8x8[1, K[I]];
  1717.     DoXOR(@L, @L, BoxKey[2].L shr 8);
  1718.     A := BoxKey[0].B;
  1719.     B := BoxKey[1].B;
  1720.     for I := 0 to 255 do
  1721.       Box[1, I] := Twofish_Data[1, Twofish_8x8[0, Twofish_8x8[1, L[I]] xor B] xor A];
  1722.     DoXOR(@K, @Twofish_8x8[0],BoxKey[3].L shr 16);
  1723.     for I := 0 to 255 do L[I] := Twofish_8x8[0, K[I]];
  1724.     DoXOR(@L, @L, BoxKey[2].L shr 16);
  1725.     A := BoxKey[0].C;
  1726.     B := BoxKey[1].C;
  1727.     for I := 0 to 255 do
  1728.       Box[2, I] := Twofish_Data[2, Twofish_8x8[1, Twofish_8x8[0, L[I]] xor B] xor A];
  1729.     DoXOR(@K, @Twofish_8x8[1], BoxKey[3].L shr 24);
  1730.     for I := 0 to 255 do L[I] := Twofish_8x8[0, K[I]];
  1731.     DoXOR(@L, @L, BoxKey[2].L shr 24);
  1732.     A := BoxKey[0].D;
  1733.     B := BoxKey[1].D;
  1734.     for I := 0 to 255 do
  1735.       Box[3, I] := Twofish_Data[3, Twofish_8x8[1, Twofish_8x8[1, L[I]] xor B] xor A];
  1736.   end;
  1737.  
  1738. begin
  1739.   SubKey := FUser;
  1740.   Box    := @SubKey[40];
  1741.   SetupKey;
  1742.   if Size = 16 then SetupBox128 else
  1743.     if Size = 24 then SetupBox192
  1744.       else SetupBox256;
  1745. end;
  1746.  
  1747. procedure TCipher_Twofish.DoEncode(Source, Dest: Pointer; Size: Integer);
  1748. var
  1749.   S: PLongArray;
  1750.   Box: PTwofishBox;
  1751.   I,X,Y: LongWord;
  1752.   A,B,C,D: TLongRec;
  1753. begin
  1754.   Assert(Size = Context.BlockSize);
  1755.  
  1756.   S   := FUser;
  1757.   A.L := PLongArray(Source)[0] xor S[0];
  1758.   B.L := PLongArray(Source)[1] xor S[1];
  1759.   C.L := PLongArray(Source)[2] xor S[2];
  1760.   D.L := PLongArray(Source)[3] xor S[3];
  1761.  
  1762.   Box := @S[40];
  1763.   S   := @S[8];
  1764.   for I := 0 to 7 do
  1765.   begin
  1766.     X := Box[0, A.A] xor Box[1, A.B] xor Box[2, A.C] xor Box[3, A.D];
  1767.     Y := Box[1, B.A] xor Box[2, B.B] xor Box[3, B.C] xor Box[0, B.D];
  1768.     D.L := D.L shl 1 or D.L shr 31;
  1769.     C.L := C.L xor (X + Y       + S[0]);
  1770.     D.L := D.L xor (X + Y shl 1 + S[1]);
  1771.     C.L := C.L shr 1 or C.L shl 31;
  1772.  
  1773.     X := Box[0, C.A] xor Box[1, C.B] xor Box[2, C.C] xor Box[3, C.D];
  1774.     Y := Box[1, D.A] xor Box[2, D.B] xor Box[3, D.C] xor Box[0, D.D];
  1775.     B.L := B.L shl 1 or B.L shr 31;
  1776.     A.L := A.L xor (X + Y       + S[2]);
  1777.     B.L := B.L xor (X + Y shl 1 + S[3]);
  1778.     A.L := A.L shr 1 or A.L shl 31;
  1779.  
  1780.     S := @S[4];
  1781.   end;
  1782.   S := FUser;
  1783.   PLongArray(Dest)[0] := C.L xor S[4];
  1784.   PLongArray(Dest)[1] := D.L xor S[5];
  1785.   PLongArray(Dest)[2] := A.L xor S[6];
  1786.   PLongArray(Dest)[3] := B.L xor S[7];
  1787. end;
  1788.  
  1789. procedure TCipher_Twofish.DoDecode(Source, Dest: Pointer; Size: Integer);
  1790. var
  1791.   S: PLongArray;
  1792.   Box: PTwofishBox;
  1793.   I,X,Y: LongWord;
  1794.   A,B,C,D: TLongRec;
  1795. begin
  1796.   Assert(Size = Context.BlockSize);
  1797.  
  1798.   S := FUser;
  1799.   Box := @S[40];
  1800.   C.L := PLongArray(Source)[0] xor S[4];
  1801.   D.L := PLongArray(Source)[1] xor S[5];
  1802.   A.L := PLongArray(Source)[2] xor S[6];
  1803.   B.L := PLongArray(Source)[3] xor S[7];
  1804.   S := @S[36];
  1805.   for I := 0 to 7 do
  1806.   begin
  1807.     X := Box[0, C.A] xor Box[1, C.B] xor Box[2, C.C] xor Box[3, C.D];
  1808.     Y := Box[0, D.D] xor Box[1, D.A] xor Box[2, D.B] xor Box[3, D.C];
  1809.     A.L := A.L shl 1 or A.L shr 31;
  1810.     B.L := B.L xor (X + Y shl 1 + S[3]);
  1811.     A.L := A.L xor (X + Y       + S[2]);
  1812.     B.L := B.L shr 1 or B.L shl 31;
  1813.  
  1814.     X := Box[0, A.A] xor Box[1, A.B] xor Box[2, A.C] xor Box[3, A.D];
  1815.     Y := Box[0, B.D] xor Box[1, B.A] xor Box[2, B.B] xor Box[3, B.C];
  1816.     C.L := C.L shl 1 or C.L shr 31;
  1817.     D.L := D.L xor (X + Y shl 1 + S[1]);
  1818.     C.L := C.L xor (X + Y       + S[0]);
  1819.     D.L := D.L shr 1 or D.L shl 31;
  1820.  
  1821.     Dec(PLongWord(S), 4);
  1822.   end;
  1823.   S := FUser;
  1824.   PLongArray(Dest)[0] := A.L xor S[0];
  1825.   PLongArray(Dest)[1] := B.L xor S[1];
  1826.   PLongArray(Dest)[2] := C.L xor S[2];
  1827.   PLongArray(Dest)[3] := D.L xor S[3];
  1828. end;
  1829.  
  1830. // .TCipher_IDEA
  1831. class function TCipher_IDEA.Context: TCipherContext;
  1832. begin
  1833.   Result.KeySize := 16;
  1834.   Result.BufferSize := 8;
  1835.   Result.BlockSize := 8;
  1836.   Result.UserSize := 208;
  1837.   Result.UserSave := False;
  1838. end;
  1839.  
  1840. procedure TCipher_IDEA.DoInit(const Key; Size: Integer);
  1841.  
  1842.   function IDEAInv(X: Word): Word;
  1843.   var
  1844.     A, B, C, D: Word;
  1845.   begin
  1846.     if X <= 1 then
  1847.     begin
  1848.       Result := X;
  1849.       Exit;
  1850.     end;
  1851.     A := 1;
  1852.     B := $10001 div X;
  1853.     C := $10001 mod X;
  1854.     while C <> 1 do
  1855.     begin
  1856.       D := X div C;
  1857.       X := X mod C;
  1858.       Inc(A, B * D);
  1859.       if X = 1 then
  1860.       begin
  1861.         Result := A;
  1862.         Exit;
  1863.       end;
  1864.       D := C div X;
  1865.       C := C mod X;
  1866.       Inc(B, A * D);
  1867.     end;
  1868.     Result := 1 - B;
  1869.   end;
  1870.  
  1871. var
  1872.   I: Integer;
  1873.   E: PWordArray;
  1874.   A,B,C: Word;
  1875.   K,D: PWordArray;
  1876. begin
  1877.   E := FUser;
  1878.   Move(Key, E^, Size);
  1879.   for I := 0 to 7 do E[I] := Swap(E[I]);
  1880.   for I := 0 to 39 do
  1881.     E[I + 8] := E[I and not 7 + (I + 1) and 7] shl 9 or
  1882.                 E[I and not 7 + (I + 2) and 7] shr 7;
  1883.   for I := 41 to 44 do
  1884.     E[I + 7] := E[I] shl 9 or E[I + 1] shr 7;
  1885.   K  := E;
  1886.   D  := @E[100];
  1887.   A  := IDEAInv(K[0]);
  1888.   B  := 0 - K[1];
  1889.   C  := 0 - K[2];
  1890.   D[3] := IDEAInv(K[3]);
  1891.   D[2] := C;
  1892.   D[1] := B;
  1893.   D[0] := A;
  1894.   Inc(PWord(K), 4);
  1895.   for I := 1 to 8 do
  1896.   begin
  1897.     Dec(PWord(D), 6);
  1898.     A    := K[0];
  1899.     D[5] := K[1];
  1900.     D[4] := A;
  1901.     A    := IDEAInv(K[2]);
  1902.     B    := 0 - K[3];
  1903.     C    := 0 - K[4];
  1904.     D[3] := IDEAInv(K[5]);
  1905.     D[2] := B;
  1906.     D[1] := C;
  1907.     D[0] := A;
  1908.     Inc(PWord(K), 6);
  1909.   end;
  1910.   A    := D[2];
  1911.   D[2] := D[1];
  1912.   D[1] := A;
  1913. end;
  1914.  
  1915. function IDEAMul(X,Y: LongWord): LongWord;
  1916. asm
  1917.        AND    EAX,0FFFFh
  1918.        JZ     @@1
  1919.        AND    EDX,0FFFFh
  1920.        JZ     @@1
  1921.        MUL    EDX
  1922.        MOV    EDX,EAX
  1923.        MOV    ECX,EAX
  1924.        SHR    EDX,16
  1925.        SUB    EAX,EDX
  1926.        SUB    CX,AX
  1927.        ADC    EAX,0
  1928.        RET
  1929. @@1:   LEA    EAX,[EAX + EDX -1]
  1930.        NEG    EAX
  1931. end;
  1932.  
  1933. procedure IDEACipher(Source, Dest: PLongArray; Key: PWordArray);
  1934. var
  1935.   I: LongWord;
  1936.   X,Y,A,B,C,D: LongWord;
  1937. begin
  1938.   I := SwapLong(Source[0]);
  1939.   A := I shr 16;
  1940.   B := I and $FFFF;
  1941.   I := SwapLong(Source[1]);
  1942.   C := I shr 16;
  1943.   D := I and $FFFF;
  1944.   for I := 0 to 7 do
  1945.   begin
  1946.     A := IDEAMul(A, Key[0]);
  1947.     Inc(B, Key[1]);
  1948.     Inc(C, Key[2]);
  1949.     D := IDEAMul(D, Key[3]);
  1950.     Y := C xor A;
  1951.     Y := IDEAMul(Y, Key[4]);
  1952.     X := B xor D + Y;
  1953.     X := IDEAMul(X, Key[5]);
  1954.     Inc(Y, X);
  1955.     A := A xor X;
  1956.     D := D xor Y;
  1957.     Y := B xor Y;
  1958.     B := C xor X;
  1959.     C := Y;
  1960.     Key := @Key[6];
  1961.   end;
  1962.   Dest[0] := SwapLong(IDEAMul(A, Key[0]) shl 16 or (C + Key[1]) and $FFFF);
  1963.   Dest[1] := SwapLong((B + Key[2]) shl 16 or IDEAMul(D, Key[3]) and $FFFF);
  1964. end;
  1965.  
  1966. procedure TCipher_IDEA.DoEncode(Source, Dest: Pointer; Size: Integer);
  1967. begin
  1968.   Assert(Size = Context.BlockSize);
  1969.  
  1970.   IDEACipher(Source, Dest, FUser);
  1971. end;
  1972.  
  1973. procedure TCipher_IDEA.DoDecode(Source, Dest: Pointer; Size: Integer);
  1974. begin
  1975.   Assert(Size = Context.BlockSize);
  1976.  
  1977.   IDEACipher(Source, Dest, @PLongArray(FUser)[26]);
  1978. end;
  1979.  
  1980. // .TCipher_Cast256
  1981. class function TCipher_Cast256.Context: TCipherContext;
  1982. begin
  1983.   Result.KeySize := 32;
  1984.   Result.BlockSize := 16;
  1985.   Result.BufferSize := 16;
  1986.   Result.UserSize := 384;
  1987.   Result.UserSave := False;
  1988. end;
  1989.  
  1990. procedure TCipher_Cast256.DoInit(const Key; Size: Integer);
  1991. var
  1992.   X: array[0..7] of LongWord;
  1993.   M, R, I, J, T: LongWord;
  1994.   K: PLongArray;
  1995. begin
  1996.   FillChar(X, SizeOf(X), 0);
  1997.   Move(Key, X, Size);
  1998.   SwapLongBuffer(X, X, 8);
  1999.   K := FUser;
  2000.   M := $5A827999;
  2001.   R := 19;
  2002.   for I := 0 to 11 do
  2003.   begin
  2004.     for J := 0 to 1 do
  2005.     begin
  2006.       T := M + X[7];
  2007.       T := T shl R or T shr (32 - R);
  2008.       X[6] := X[6] xor (Cast256_Data[0, T shr 24] xor
  2009.                         Cast256_Data[1, T shr 16 and $FF] -
  2010.                         Cast256_Data[2, T shr  8 and $FF] +
  2011.                         Cast256_Data[3, T and $FF]);
  2012.       Inc(M, $6ED9EBA1);
  2013.       Inc(R, 17);
  2014.       T := M xor X[6];
  2015.       T := T shl R or T shr (32 - R);
  2016.       X[5] := X[5] xor (Cast256_Data[0, T shr 24] -
  2017.                         Cast256_Data[1, T shr 16 and $FF] +
  2018.                         Cast256_Data[2, T shr  8 and $FF] xor
  2019.                         Cast256_Data[3, T and $FF]);
  2020.       Inc(M, $6ED9EBA1);
  2021.       Inc(R, 17);
  2022.       T := M - X[5];
  2023.       T := T shl R or T shr (32 - R);
  2024.       X[4] := X[4] xor (Cast256_Data[0, T shr 24] +
  2025.                         Cast256_Data[1, T shr 16 and $FF] xor
  2026.                         Cast256_Data[2, T shr  8 and $FF] -
  2027.                         Cast256_Data[3, T and $FF]);
  2028.       Inc(M, $6ED9EBA1);
  2029.       Inc(R, 17);
  2030.       T := M + X[4];
  2031.       T := T shl R or T shr (32 - R);
  2032.       X[3] := X[3] xor (Cast256_Data[0, T shr 24] xor
  2033.                         Cast256_Data[1, T shr 16 and $FF] -
  2034.                         Cast256_Data[2, T shr  8 and $FF] +
  2035.                         Cast256_Data[3, T and $FF]);
  2036.       Inc(M, $6ED9EBA1);
  2037.       Inc(R, 17);
  2038.       T := M xor X[3];
  2039.       T := T shl R or T shr (32 - R);
  2040.       X[2] := X[2] xor (Cast256_Data[0, T shr 24] -
  2041.                         Cast256_Data[1, T shr 16 and $FF] +
  2042.                         Cast256_Data[2, T shr  8 and $FF] xor
  2043.                         Cast256_Data[3, T and $FF]);
  2044.       Inc(M, $6ED9EBA1);
  2045.       Inc(R, 17);
  2046.       T := M - X[2];
  2047.       T := T shl R or T shr (32 - R);
  2048.       X[1] := X[1] xor (Cast256_Data[0, T shr 24] +
  2049.                         Cast256_Data[1, T shr 16 and $FF] xor
  2050.                         Cast256_Data[2, T shr  8 and $FF] -
  2051.                         Cast256_Data[3, T and $FF]);
  2052.       Inc(M, $6ED9EBA1);
  2053.       Inc(R, 17);
  2054.       T := M + X[1];
  2055.       T := T shl R or T shr (32 - R);
  2056.       X[0] := X[0] xor (Cast256_Data[0, T shr 24] xor
  2057.                         Cast256_Data[1, T shr 16 and $FF] -
  2058.                         Cast256_Data[2, T shr  8 and $FF] +
  2059.                         Cast256_Data[3, T and $FF]);
  2060.       Inc(M, $6ED9EBA1);
  2061.       Inc(R, 17);
  2062.       T := M xor X[0];
  2063.       T := T shl R or T shr (32 - R);
  2064.       X[7] := X[7] xor (Cast256_Data[0, T shr 24] -
  2065.                         Cast256_Data[1, T shr 16 and $FF] +
  2066.                         Cast256_Data[2, T shr  8 and $FF] xor
  2067.                         Cast256_Data[3, T and $FF]);
  2068.       Inc(M, $6ED9EBA1);
  2069.       Inc(R, 17);
  2070.     end;
  2071.     if I < 6 then
  2072.     begin
  2073.       K[48] := X[0] and $1F;
  2074.       K[49] := X[2] and $1F;
  2075.       K[50] := X[4] and $1F;
  2076.       K[51] := X[6] and $1F;
  2077.       K[0] := X[7];
  2078.       K[1] := X[5];
  2079.       K[2] := X[3];
  2080.       K[3] := X[1];
  2081.     end else
  2082.     begin
  2083.       K[48] := X[6] and $1F;
  2084.       K[49] := X[4] and $1F;
  2085.       K[50] := X[2] and $1F;
  2086.       K[51] := X[0] and $1F;
  2087.       K[0] := X[1];
  2088.       K[1] := X[3];
  2089.       K[2] := X[5];
  2090.       K[3] := X[7];
  2091.     end;
  2092.     K := @K[4];
  2093.   end;
  2094.   ProtectBuffer(X, SizeOf(X));
  2095. end;
  2096.  
  2097. procedure TCipher_Cast256.DoEncode(Source, Dest: Pointer; Size: Integer);
  2098. var
  2099.   I,T,A,B,C,D: LongWord;
  2100.   K: PLongArray;
  2101. begin
  2102.   Assert(Size = Context.BlockSize);
  2103.  
  2104.   K := FUser;
  2105.   SwapLongBuffer(Source^, Dest^, 4);
  2106.   A := PLongArray(Dest)[0];
  2107.   B := PLongArray(Dest)[1];
  2108.   C := PLongArray(Dest)[2];
  2109.   D := PLongArray(Dest)[3];
  2110.   for I := 0 to 5 do
  2111.   begin
  2112.     T := K[0] + D;
  2113.     T := T shl K[48] or T shr (32 - K[48]);
  2114.     C := C xor (Cast256_Data[0, T shr 24] xor
  2115.                 Cast256_Data[1, T shr 16 and $FF] -
  2116.                 Cast256_Data[2, T shr  8 and $FF] +
  2117.                 Cast256_Data[3, T and $FF]);
  2118.     T := K[1] xor C;
  2119.     T := T shl K[49] or T shr (32 - K[49]);
  2120.     B := B xor (Cast256_Data[0, T shr 24] -
  2121.                 Cast256_Data[1, T shr 16 and $FF] +
  2122.                 Cast256_Data[2, T shr  8 and $FF] xor
  2123.                 Cast256_Data[3, T and $FF]);
  2124.     T := K[2] - B;
  2125.     T := T shl K[50] or T shr (32 - K[50]);
  2126.     A := A xor (Cast256_Data[0, T shr 24] +
  2127.                 Cast256_Data[1, T shr 16 and $FF] xor
  2128.                 Cast256_Data[2, T shr  8 and $FF] -
  2129.                 Cast256_Data[3, T and $FF]);
  2130.     T := K[3] + A;
  2131.     T := T shl K[51] or T shr (32 - K[51]);
  2132.     D := D xor (Cast256_Data[0, T shr 24] xor
  2133.                 Cast256_Data[1, T shr 16 and $FF] -
  2134.                 Cast256_Data[2, T shr  8 and $FF] +
  2135.                 Cast256_Data[3, T and $FF]);
  2136.     K := @K[4];
  2137.   end;
  2138.   for I := 0 to 5 do
  2139.   begin
  2140.     T := K[0] + A;
  2141.     T := T shl K[48] or T shr (32 - K[48]);
  2142.     D := D xor (Cast256_Data[0, T shr 24] xor
  2143.                 Cast256_Data[1, T shr 16 and $FF] -
  2144.                 Cast256_Data[2, T shr  8 and $FF] +
  2145.                 Cast256_Data[3, T and $FF]);
  2146.     T := K[1] - B;
  2147.     T := T shl K[49] or T shr (32 - K[49]);
  2148.     A := A xor (Cast256_Data[0, T shr 24] +
  2149.                 Cast256_Data[1, T shr 16 and $FF] xor
  2150.                 Cast256_Data[2, T shr  8 and $FF] -
  2151.                 Cast256_Data[3, T and $FF]);
  2152.     T := K[2] xor C;
  2153.     T := T shl K[50] or T shr (32 - K[50]);
  2154.     B := B xor (Cast256_Data[0, T shr 24] -
  2155.                 Cast256_Data[1, T shr 16 and $FF] +
  2156.                 Cast256_Data[2, T shr  8 and $FF] xor
  2157.                 Cast256_Data[3, T and $FF]);
  2158.     T := K[3] + D;
  2159.     T := T shl K[51] or T shr (32 - K[51]);
  2160.     C := C xor (Cast256_Data[0, T shr 24] xor
  2161.                 Cast256_Data[1, T shr 16 and $FF] -
  2162.                 Cast256_Data[2, T shr  8 and $FF] +
  2163.                 Cast256_Data[3, T and $FF]);
  2164.     K := @K[4];
  2165.   end;
  2166.   PLongArray(Dest)[0] := A;
  2167.   PLongArray(Dest)[1] := B;
  2168.   PLongArray(Dest)[2] := C;
  2169.   PLongArray(Dest)[3] := D;
  2170.   SwapLongBuffer(Dest^, Dest^, 4);
  2171. end;
  2172.  
  2173. procedure TCipher_Cast256.DoDecode(Source, Dest: Pointer; Size: Integer);
  2174. var
  2175.   I,T,A,B,C,D: LongWord;
  2176.   K: PLongArray;
  2177. begin
  2178.   Assert(Size = Context.BlockSize);
  2179.  
  2180.   K := @PLongArray(FUser)[44];
  2181.   SwapLongBuffer(Source^, Dest^, 4);
  2182.   A := PLongArray(Dest)[0];
  2183.   B := PLongArray(Dest)[1];
  2184.   C := PLongArray(Dest)[2];
  2185.   D := PLongArray(Dest)[3];
  2186.   for I := 0 to 5 do
  2187.   begin
  2188.     T := K[3] + D;
  2189.     T := T shl K[51] or T shr (32 - K[51]);
  2190.     C := C xor (Cast256_Data[0, T shr 24] xor
  2191.                 Cast256_Data[1, T shr 16 and $FF] -
  2192.                 Cast256_Data[2, T shr  8 and $FF] +
  2193.                 Cast256_Data[3, T and $FF]);
  2194.     T := K[2] xor C;
  2195.     T := T shl K[50] or T shr (32 - K[50]);
  2196.     B := B xor (Cast256_Data[0, T shr 24] -
  2197.                 Cast256_Data[1, T shr 16 and $FF] +
  2198.                 Cast256_Data[2, T shr  8 and $FF] xor
  2199.                 Cast256_Data[3, T and $FF]);
  2200.     T := K[1] - B;
  2201.     T := T shl K[49] or T shr (32 - K[49]);
  2202.     A := A xor (Cast256_Data[0, T shr 24] +
  2203.                 Cast256_Data[1, T shr 16 and $FF] xor
  2204.                 Cast256_Data[2, T shr  8 and $FF] -
  2205.                 Cast256_Data[3, T and $FF]);
  2206.     T := K[0] + A;
  2207.     T := T shl K[48] or T shr (32 - K[48]);
  2208.     D := D xor (Cast256_Data[0, T shr 24] xor
  2209.                 Cast256_Data[1, T shr 16 and $FF] -
  2210.                 Cast256_Data[2, T shr  8 and $FF] +
  2211.                 Cast256_Data[3, T and $FF]);
  2212.     Dec(PLongWord(K), 4);
  2213.   end;
  2214.   for I := 0 to 5 do
  2215.   begin
  2216.     T := K[3] + A;
  2217.     T := T shl K[51] or T shr (32 - K[51]);
  2218.     D := D xor (Cast256_Data[0, T shr 24] xor
  2219.                 Cast256_Data[1, T shr 16 and $FF] -
  2220.                 Cast256_Data[2, T shr  8 and $FF] +
  2221.                 Cast256_Data[3, T and $FF]);
  2222.     T := K[2] - B;
  2223.     T := T shl K[50] or T shr (32 - K[50]);
  2224.     A := A xor (Cast256_Data[0, T shr 24] +
  2225.                 Cast256_Data[1, T shr 16 and $FF] xor
  2226.                 Cast256_Data[2, T shr  8 and $FF] -
  2227.                 Cast256_Data[3, T and $FF]);
  2228.     T := K[1] xor C;
  2229.     T := T shl K[49] or T shr (32 - K[49]);
  2230.     B := B xor (Cast256_Data[0, T shr 24] -
  2231.                 Cast256_Data[1, T shr 16 and $FF] +
  2232.                 Cast256_Data[2, T shr  8 and $FF] xor
  2233.                 Cast256_Data[3, T and $FF]);
  2234.     T := K[0] + D;
  2235.     T := T shl K[48] or T shr (32 - K[48]);
  2236.     C := C xor (Cast256_Data[0, T shr 24] xor
  2237.                 Cast256_Data[1, T shr 16 and $FF] -
  2238.                 Cast256_Data[2, T shr  8 and $FF] +
  2239.                 Cast256_Data[3, T and $FF]);
  2240.     Dec(PLongWord(K), 4);
  2241.   end;
  2242.   PLongArray(Dest)[0] := A;
  2243.   PLongArray(Dest)[1] := B;
  2244.   PLongArray(Dest)[2] := C;
  2245.   PLongArray(Dest)[3] := D;
  2246.   SwapLongBuffer(Dest^, Dest^, 4);
  2247. end;
  2248.  
  2249. // .TCipher_Mars
  2250. class function TCipher_Mars.Context: TCipherContext;
  2251. begin
  2252.   Result.KeySize := 56;
  2253.   Result.BlockSize := 16;
  2254.   Result.BufferSize := 16;
  2255.   Result.UserSize := 160;
  2256.   Result.UserSave := False;
  2257. end;
  2258.  
  2259. procedure TCipher_Mars.DoInit(const Key; Size: Integer);
  2260. var
  2261.   B: PLongArray;
  2262.  
  2263.   function FixKey(K, R: LongWord): LongWord;
  2264.   var
  2265.     M1,M2: LongWord;
  2266.     I: LongWord;
  2267.   begin
  2268.     I := K and 3;
  2269.     K := K or 3;
  2270.     M1 := not K xor (K shl 1);
  2271.     M2 := M1 and (M1 shl 1);
  2272.     M2 := M2 and (M2 shl 2);
  2273.     M2 := M2 and (M2 shl 4);
  2274.     M2 := M2 and (M1 shl 8);
  2275.     M2 := M2 and $FFFFFE00;
  2276.     if M2 = 0 then
  2277.     begin
  2278.       Result := K;
  2279.       Exit;
  2280.     end;
  2281.     M1 := M2 or (M2 shr 1);
  2282.     M1 := M1 or (M1 shr 2);
  2283.     M1 := M1 or (M2 shr 4);
  2284.     M1 := M1 or (M1 shr 5);
  2285.     M1 := M1 and ((not K xor (K shl 1)) and (not K xor (K shr 1)) and $7FFFFFFC);
  2286.     Result := K xor ((B[265 + I] shl R or B[265 + I] shr (32 - R)) and M1);
  2287.   end;
  2288.  
  2289. var
  2290.   T: array[0..14] of LongWord;
  2291.   I,J,L: LongWord;
  2292.   U: LongWord;
  2293.   K: PLongArray;
  2294. begin
  2295.   K := FUser;
  2296.   B := @Mars_Data;
  2297.   FillChar(T, SizeOf(T), 0);
  2298.   Move(Key, T, Size);
  2299.   Size := Size div 4;
  2300.   T[Size] := Size;
  2301.   for J := 0 to 3 do
  2302.   begin
  2303.     for I := 0 to 14 do
  2304.     begin
  2305.       U := T[(I + 8) mod 15] xor T[(I + 13) mod 15];
  2306.       T[I] := T[I] xor (U shl 3 or U shr 29) xor (I * 4 + J);
  2307.     end;
  2308.     for L := 0 to 3 do
  2309.     begin
  2310.       for I := 0 to 14 do
  2311.       begin
  2312.         Inc(T[I], B[T[(I + 14) mod 15] and $1FF]);
  2313.         T[I] := T[I] shl 9 or T[I] shr 23;
  2314.       end;
  2315.     end;
  2316.     for I := 0 to 9 do
  2317.       K[(J * 10) + I] := T[(I * 4) mod 15];
  2318.   end;
  2319.   I := 5;
  2320.   repeat
  2321.     K[I] := FixKey(K[I], K[I - 1]);
  2322.     Inc(I, 2);
  2323.   until I >= 37;
  2324. end;
  2325.  
  2326.  
  2327. procedure TCipher_Mars.DoEncode(Source, Dest: Pointer; Size: Integer);
  2328. var
  2329.   K: PLongArray;
  2330.   I,L,R,A,B,C,D: LongWord;
  2331. begin
  2332.   Assert(Size = Context.BlockSize);
  2333.  
  2334.   K := FUser;
  2335.   A := PLongArray(Source)[0] + K[0];
  2336.   B := PLongArray(Source)[1] + K[1];
  2337.   C := PLongArray(Source)[2] + K[2];
  2338.   D := PLongArray(Source)[3] + K[3];
  2339.   K := @K[4];
  2340.   for I := 0 to 1 do
  2341.   begin
  2342.     B := B xor Mars_Data[A and $FF] + Mars_Data[A shr 8 and $FF + 256];
  2343.     Inc(C, Mars_Data[A shr 16 and $FF]);
  2344.     D := D xor Mars_Data[A shr 24 + 256];
  2345.     A := (A shr 24 or A shl 8) + D;
  2346.  
  2347.     C := C xor Mars_Data[B and $FF] + Mars_Data[B shr 8 and $FF + 256];
  2348.     Inc(D, Mars_Data[B shr 16 and $FF]);
  2349.     A := A xor Mars_Data[B shr 24 + 256];
  2350.     B := (B shr 24 or B shl 8) + C;
  2351.  
  2352.     D := D xor Mars_Data[C and $FF] + Mars_Data[C shr 8 and $FF + 256];
  2353.     Inc(A, Mars_Data[C shr 16 and $FF]);
  2354.     B := B xor Mars_Data[C shr 24 + 256];
  2355.     C := C shr 24 or C shl 8;
  2356.  
  2357.     A := A xor Mars_Data[D and $FF] + Mars_Data[D shr 8 and $FF + 256];
  2358.     Inc(B, Mars_Data[D shr 16 and $FF]);
  2359.     C := C xor Mars_Data[D shr 24 + 256];
  2360.     D := D shr 24 or D shl 8;
  2361.   end;
  2362.  
  2363.   for I := 0 to 3 do
  2364.   begin
  2365.     L := A + K[0];
  2366.     A := A shl 13 or A shr 19;
  2367.     R := A * K[1];
  2368.     R := R shl 5 or R shr 27;
  2369.     Inc(C, L shl R or L shr (32 - R));
  2370.     L := Mars_Data[L and $1FF] xor R;
  2371.     R := R shl 5 or R shr 27;
  2372.     L := L xor R;
  2373.     L := L shl R or L shr (32 - R);
  2374.  
  2375.     if I <= 1 then
  2376.     begin
  2377.       Inc(B, L);
  2378.       D := D xor R;
  2379.     end else
  2380.     begin
  2381.       Inc(D, L);
  2382.       B := B xor R;
  2383.     end;
  2384.     L := B + K[2];
  2385.     B := B shl 13 or B shr 19;
  2386.     R := B * K[3];
  2387.     R := R shl 5 or R shr 27;
  2388.     Inc(D, L shl R or L shr (32 - R));
  2389.     L := Mars_Data[L and $1FF] xor R;
  2390.     R := R shl 5 or R shr 27;
  2391.     L := L xor R;
  2392.     L := L shl R or L shr (32 - R);
  2393.     if I <= 1 then
  2394.     begin
  2395.       Inc(C, L);
  2396.       A := A xor R;
  2397.     end else
  2398.     begin
  2399.       Inc(A, L);
  2400.       C := C xor R;
  2401.     end;
  2402.     L := C + K[4];
  2403.     C := C shl 13 or C shr 19;
  2404.     R := C * K[5];
  2405.     R := R shl 5 or R shr 27;
  2406.     Inc(A, L shl R or L shr (32 - R));
  2407.     L := Mars_Data[L and $1FF] xor R;
  2408.     R := R shl 5 or R shr 27;
  2409.     L := L xor R;
  2410.     L := L shl R or L shr (32 - R);
  2411.     if I <= 1 then
  2412.     begin
  2413.       Inc(D, L);
  2414.       B := B xor R;
  2415.     end else
  2416.     begin
  2417.       Inc(B, L);
  2418.       D := D xor R;
  2419.     end;
  2420.     L := D + K[6];
  2421.     D := D shl 13 or D shr 19;
  2422.     R := D * K[7];
  2423.     R := R shl 5 or R shr 27;
  2424.     Inc(B, L shl R or L shr (32 - R));
  2425.     L := Mars_Data[L and $1FF] xor R;
  2426.     R := R shl 5 or R shr 27;
  2427.     L := L xor R;
  2428.     L := L shl R or L shr (32 - R);
  2429.     if I <= 1 then
  2430.     begin
  2431.       Inc(A, L);
  2432.       C := C xor R;
  2433.     end else
  2434.     begin
  2435.       Inc(C, L);
  2436.       A := A xor R;
  2437.     end;
  2438.     K := @K[8];
  2439.   end;
  2440.   for I := 0 to 1 do
  2441.   begin
  2442.     B := B xor Mars_Data[A and $FF + 256];
  2443.     Dec(C, Mars_Data[A shr 24]);
  2444.     D := D - Mars_Data[A shr 16 and $FF + 256] xor Mars_Data[A shr 8 and $FF];
  2445.     A := A shl 24 or A shr 8;
  2446.     C := C xor Mars_Data[B and $FF + 256];
  2447.     Dec(D, Mars_Data[B shr 24]);
  2448.     A := A - Mars_Data[B shr 16 and $FF + 256] xor Mars_Data[B shr 8 and $FF];
  2449.     B := B shl 24 or B shr 8;
  2450.     Dec(C, B);
  2451.     D := D xor Mars_Data[C and $FF + 256];
  2452.     Dec(A, Mars_Data[C shr 24]);
  2453.     B := B - Mars_Data[C shr 16 and $FF + 256] xor Mars_Data[C shr 8 and $FF];
  2454.     C := C shl 24 or C shr 8;
  2455.     Dec(D, A);
  2456.     A := A xor Mars_Data[D and $FF + 256];
  2457.     Dec(B, Mars_Data[D shr 24]);
  2458.     C := C - Mars_Data[D shr 16 and $FF + 256] xor Mars_Data[D shr 8 and $FF];
  2459.     D := D shl 24 or D shr 8;
  2460.   end;
  2461.   PLongArray(Dest)[0] := A - K[0];
  2462.   PLongArray(Dest)[1] := B - K[1];
  2463.   PLongArray(Dest)[2] := C - K[2];
  2464.   PLongArray(Dest)[3] := D - K[3];
  2465. end;
  2466.  
  2467. procedure TCipher_Mars.DoDecode(Source, Dest: Pointer; Size: Integer);
  2468. var
  2469.   K: PLongArray;
  2470.   I,L,R,A,B,C,D: LongWord;
  2471. begin
  2472.   Assert(Size = Context.BlockSize);
  2473.  
  2474.   K := @PLongArray(FUser)[28];
  2475.   A := PLongArray(Source)[0] + K[8];
  2476.   B := PLongArray(Source)[1] + K[9];
  2477.   C := PLongArray(Source)[2] + K[10];
  2478.   D := PLongArray(Source)[3] + K[11];
  2479.   for I := 0 to 1 do
  2480.   begin
  2481.     D := D shr 24 or D shl 8;
  2482.     C := C xor Mars_Data[D shr 8 and $FF] + Mars_Data[D shr 16 and $FF + 256];
  2483.     Inc(B, Mars_Data[D shr 24]);
  2484.     A := A xor Mars_Data[D and $FF + 256];
  2485.     Inc(D, A);
  2486.     C := C shr 24 or C shl 8;
  2487.     B := B xor Mars_Data[C shr 8 and $FF] + Mars_Data[C shr 16 and $FF + 256];
  2488.     Inc(A, Mars_Data[C shr 24]);
  2489.     D := D xor Mars_Data[C and $FF + 256];
  2490.     Inc(C, B);
  2491.     B := B shr 24 or B shl 8;
  2492.     A := A xor Mars_Data[B shr 8 and $FF] + Mars_Data[B shr 16 and $FF + 256];
  2493.     Inc(D, Mars_Data[B shr 24]);
  2494.     C := C xor Mars_Data[B and $FF + 256];
  2495.     A := A shr 24 or A shl 8;
  2496.     D := D xor Mars_Data[A shr 8 and $FF] + Mars_Data[A shr 16 and $FF + 256];
  2497.     Inc(C, Mars_Data[A shr 24]);
  2498.     B := B xor Mars_Data[A and $FF + 256];
  2499.   end;
  2500.   for I := 0 to 3 do
  2501.   begin
  2502.     R := D * K[7];
  2503.     R := R shl 5 or R shr 27;
  2504.     D := D shr 13 or D shl 19;
  2505.     L := D + K[6];
  2506.     Dec(B, L shl R or L shr (32 - R));
  2507.     L := Mars_Data[L and $1FF] xor R;
  2508.     R := R shl 5 or R shr 27;
  2509.     L := L xor R;
  2510.     L := L shl R or L shr (32 - R);
  2511.     if I <= 1 then
  2512.     begin
  2513.       Dec(C, L);
  2514.       A := A xor R;
  2515.     end else
  2516.     begin
  2517.       Dec(A, L);
  2518.       C := C xor R;
  2519.     end;
  2520.     R := C * K[5];
  2521.     R := R shl 5 or R shr 27;
  2522.     C := C shr 13 or C shl 19;
  2523.     L := C + K[4];
  2524.     Dec(A, L shl R or L shr (32 - R));
  2525.     L := Mars_Data[L and $1FF] xor R;
  2526.     R := R shl 5 or R shr 27;
  2527.     L := L xor R;
  2528.     L := L shl R or L shr (32 - R);
  2529.     if I <= 1 then
  2530.     begin
  2531.       Dec(B, L);
  2532.       D := D xor R;
  2533.     end else
  2534.     begin
  2535.       Dec(D, L);
  2536.       B := B xor R;
  2537.     end;
  2538.     R := B * K[3];
  2539.     R := R shl 5 or R shr 27;
  2540.     B := B shr 13 or B shl 19;
  2541.     L := B + K[2];
  2542.     Dec(D, L shl R or L shr (32 - R));
  2543.     L := Mars_Data[L and $1FF] xor R;
  2544.     R := R shl 5 or R shr 27;
  2545.     L := L xor R;
  2546.     L := L shl R or L shr (32 - R);
  2547.     if I <= 1 then
  2548.     begin
  2549.       Dec(A, L);
  2550.       C := C xor R;
  2551.     end else
  2552.     begin
  2553.       Dec(C, L);
  2554.       A := A xor R;
  2555.     end;
  2556.     R := A * K[1];
  2557.     R := R shl 5 or R shr 27;
  2558.     A := A shr 13 or A shl 19;
  2559.     L := A + K[0];
  2560.     Dec(C, L shl R or L shr (32 - R));
  2561.     L := Mars_Data[L and $1FF] xor R;
  2562.     R := R shl 5 or R shr 27;
  2563.     L := L xor R;
  2564.     L := L shl R or L shr (32 - R);
  2565.     if I <= 1 then
  2566.     begin
  2567.       Dec(D, L);
  2568.       B := B xor R;
  2569.     end else
  2570.     begin
  2571.       Dec(B, L);
  2572.       D := D xor R;
  2573.     end;
  2574.     Dec(PLongWord(K), 8);
  2575.   end;
  2576.   for I := 0 to 1 do
  2577.   begin
  2578.     D := D shl 24 or D shr 8;
  2579.     C := C xor Mars_Data[D shr 24 + 256];
  2580.     Dec(B, Mars_Data[D shr 16 and $FF]);
  2581.     A := A - Mars_Data[D shr 8 and $FF + 256] xor Mars_Data[D and $FF];
  2582.     C := C shl 24 or C shr 8;
  2583.     B := B xor Mars_Data[C shr 24 + 256];
  2584.     Dec(A, Mars_Data[C shr 16 and $FF]);
  2585.     D := D - Mars_Data[C shr 8 and $FF + 256] xor Mars_Data[C and $FF];
  2586.     Dec(B, C);
  2587.     B := B shl 24 or B shr 8;
  2588.     A := A xor Mars_Data[B shr 24 + 256];
  2589.     Dec(D, Mars_Data[B shr 16 and $FF]);
  2590.     C := C - Mars_Data[B shr 8 and $FF + 256] xor Mars_Data[B and $FF];
  2591.     Dec(A, D);
  2592.     A := A shl 24 or A shr 8;
  2593.     D := D xor Mars_Data[A shr 24 + 256];
  2594.     Dec(C, Mars_Data[A shr 16 and $FF]);
  2595.     B := B - Mars_Data[A shr 8 and $FF + 256] xor Mars_Data[A and $FF];
  2596.   end;
  2597.   PLongArray(Dest)[0] := A - K[4];
  2598.   PLongArray(Dest)[1] := B - K[5];
  2599.   PLongArray(Dest)[2] := C - K[6];
  2600.   PLongArray(Dest)[3] := D - K[7];
  2601. end;
  2602.  
  2603. // .TCipher_RC4
  2604. class function TCipher_RC4.Context: TCipherContext;
  2605. begin
  2606.   Result.KeySize := 256;
  2607.   Result.BlockSize := 1;
  2608.   Result.BufferSize := 16;
  2609.   Result.UserSize := 256 + 2;
  2610.   Result.UserSave := True;
  2611. end;
  2612.  
  2613. procedure TCipher_RC4.DoInit(const Key; Size: Integer);
  2614. var
  2615.   K: array[0..255] of Byte;
  2616.   D: PByteArray;
  2617.   I,J,T: Byte;
  2618. begin
  2619.   D := FUser;
  2620.   for I := 0 to 255 do
  2621.   begin
  2622.     D[I] := I;
  2623.     if Size > 0 then
  2624.       K[I] := TByteArray(Key)[I mod Size];
  2625.   end;
  2626.   J := 0;
  2627.   for I := 0 to 255 do
  2628.   begin
  2629.     J := J + D[I] + K[I];
  2630.     T := D[I];
  2631.     D[I] := D[J];
  2632.     D[J] := T;
  2633.   end;
  2634.   D[256] := 0;
  2635.   D[257] := 0;
  2636.   ProtectBuffer(K, SizeOf(K));
  2637. end;
  2638.  
  2639. procedure TCipher_RC4.DoEncode(Source, Dest: Pointer; Size: Integer);
  2640. var
  2641.   D: PByteArray;
  2642.   S: Integer;
  2643.   T,I,J: Byte;
  2644. begin
  2645.   D := FUser;
  2646.   I := D[256];
  2647.   J := D[257];
  2648.   for S := 0 to Size -1 do
  2649.   begin
  2650.     Inc(I);
  2651.     T := D[I];
  2652.     Inc(J, T);
  2653.     D[I] := D[J];
  2654.     D[J] := T;
  2655.     PByteArray(Dest)[S] := PByteArray(Source)[S] xor D[Byte(D[I] + T)];
  2656.   end;
  2657.   D[256] := I;
  2658.   D[257] := J;
  2659. end;
  2660.  
  2661. procedure TCipher_RC4.DoDecode(Source, Dest: Pointer; Size: Integer);
  2662. begin
  2663.   DoEncode(Source, Dest, Size);
  2664. end;
  2665.  
  2666. // .TCipher_RC6
  2667. class function TCipher_RC6.Context: TCipherContext;
  2668. begin
  2669.   Result.KeySize := 256;
  2670.   Result.BlockSize := 16;
  2671.   Result.BufferSize := 16;
  2672.   Result.UserSize := 272;
  2673.   Result.UserSave := False;
  2674. end;
  2675.  
  2676. procedure TCipher_RC6.SetRounds(Value: Integer);
  2677. begin
  2678.   if Value < 16 then Value := 16 else
  2679.     if Value > 24 then Value := 24;
  2680.   if Value <> FRounds then
  2681.   begin
  2682.     if not (FState in [csNew, csInitialized, csDone]) then Done;
  2683.     FRounds := Value;
  2684.   end;
  2685. end;
  2686.  
  2687. procedure TCipher_RC6.DoInit(const Key; Size: Integer);
  2688. var
  2689.   K: array[0..63] of LongWord;
  2690.   D: PLongArray;
  2691.   I,J,L,A,B,Z,T: LongWord;
  2692. begin
  2693.   if FRounds = 0 then FRounds := 20 else
  2694.     if FRounds < 16 then FRounds := 16 else
  2695.       if FRounds > 24 then FRounds := 24;
  2696.   D := FUser;
  2697.   FillChar(K, SizeOf(K), 0);
  2698.   Move(Key, K, Size);
  2699.   L := Size shr 2;
  2700.   if Size and 3 <> 0 then Inc(L);
  2701.   if L <= 0 then L := 1;
  2702.   J := $B7E15163;
  2703.   for I := 0 to (FRounds + 2) * 2 do
  2704.   begin
  2705.     D[I] := J;
  2706.     Inc(J, $9E3779B9);
  2707.   end;
  2708.   if L > LongWord(FRounds + 2) * 2 then Z := L * 3
  2709.     else Z := (FRounds + 2) * 6;
  2710.   I := 0;
  2711.   J := 0;
  2712.   A := 0;
  2713.   B := 0;
  2714.   for Z := Z downto 1 do
  2715.   begin
  2716.     A := A + B + D[I];
  2717.     A := A shl 3 or A shr 29;
  2718.     D[I] := A;
  2719.     T := A + B;
  2720.     B := T + K[J];
  2721.     B := B shl T or B shr (32 - T);
  2722.     K[J] := B;
  2723.     I := (I + 1) mod (LongWord(FRounds + 2) * 2);
  2724.     J := (J + 1) mod L;
  2725.   end;
  2726.   ProtectBuffer(K, SizeOf(K));
  2727. end;
  2728.  
  2729. procedure TCipher_RC6.DoEncode(Source, Dest: Pointer; Size: Integer);
  2730. {$IFDEF UseASM}
  2731. asm
  2732.       PUSH  EBX
  2733.       PUSH  ESI
  2734.       PUSH  EDI
  2735.       PUSH  EBP
  2736.       PUSH  ECX
  2737.       MOV   EBP,[EAX].TCipher_RC6.FRounds  // Rounds
  2738.       MOV   ESI,[EAX].TCipher_RC6.FUser    // Key
  2739.       MOV   EAX,[EDX +  0]   // A
  2740.       MOV   EBX,[EDX +  4]   // B
  2741.       MOV   EDI,[EDX +  8]   // C
  2742.       MOV   EDX,[EDX + 12]   // D
  2743.       ADD   EBX,[ESI + 0]    // Inc(B, K[0])
  2744.       ADD   EDX,[ESI + 4]    // Inc(D, K[1])
  2745.       ADD   ESI,8            // Inc(PInteger(K), 2)
  2746. @@1:  LEA   ECX,[EBX * 2 +1] // ECX := B * 2 +1
  2747.       IMUL  ECX,EBX          // ECX := ECX * B
  2748.       ROL   ECX,5            // T := ROL(B * (B * 2 +1), 5)
  2749.       PUSH  ECX              // save T
  2750.       XOR   EAX,ECX          // A := A xor T
  2751.       LEA   ECX,[EDX * 2 +1] // ECX := D * 2 +1
  2752.       IMUL  ECX,EDX          // ECX := ECX * D
  2753.       ROL   ECX,5            // U := ROL(D * (D * 2 +1), 5)
  2754.       XOR   EDI,ECX          // C := C xor U
  2755.       ROL   EAX,CL           // A := ROL(A xor T, U)
  2756.       POP   ECX              // restore T
  2757.       ADD   EAX,[ESI + 0]    // Inc(A, K[0])
  2758.       ROL   EDI,CL           // C := ROL(C xor U, T)
  2759.       MOV   ECX,EAX          // T := A
  2760.       ADD   EDI,[ESI + 4]    // Inc(C, K[1])
  2761.       MOV   EAX,EBX          // A := B
  2762.       MOV   EBX,EDI          // B := C
  2763.       MOV   EDI,EDX          // C := D
  2764.       DEC   EBP
  2765.       MOV   EDX,ECX          // D := T;
  2766.       LEA   ESI,[ESI + 8]    // Inc(PInteger(K), 2)
  2767.       JNZ   @@1
  2768.       ADD   EAX,[ESI + 0]    // Inc(A, K[0])
  2769.       ADD   EDI,[ESI + 4]    // Inc(C, K[1])
  2770.       POP   ECX
  2771.       MOV   [ECX +  0],EAX   // A
  2772.       MOV   [ECX +  4],EBX   // B
  2773.       MOV   [ECX +  8],EDI   // C
  2774.       MOV   [ECX + 12],EDX   // D
  2775.       POP   EBP
  2776.       POP   EDI
  2777.       POP   ESI
  2778.       POP   EBX
  2779. end;
  2780. {$ELSE}
  2781. var
  2782.   K: PLongArray;
  2783.   I,T,U,A,B,C,D: LongWord;
  2784. begin
  2785.   Assert(Size = Context.BlockSize);
  2786.  
  2787.   K := FUser;
  2788.   A := PLongArray(Source)[0];
  2789.   B := PLongArray(Source)[1] + K[0];
  2790.   C := PLongArray(Source)[2];
  2791.   D := PLongArray(Source)[3] + K[1];
  2792.   for I := 1 to FRounds do
  2793.   begin
  2794.     K := @K[2];
  2795.     T := B * (B + B +1);
  2796.     T := T shl 5 or T shr 27;
  2797.     U := D * (D + D +1);
  2798.     U := U shl 5 or U shr 27;
  2799.     A := A xor T;
  2800.     A := A shl U or A shr (32 - U) + K[0];
  2801.     C := C xor U;
  2802.     C := C shl T or C shr (32 - T) + K[1];
  2803.     T := A; A := B; B := C; C := D; D := T;
  2804.   end;
  2805.   PLongArray(Dest)[0] := A + K[2];
  2806.   PLongArray(Dest)[1] := B;
  2807.   PLongArray(Dest)[2] := C + K[3];
  2808.   PLongArray(Dest)[3] := D;
  2809. end;
  2810. {$ENDIF}
  2811.  
  2812. procedure TCipher_RC6.DoDecode(Source, Dest: Pointer; Size: Integer);
  2813. {$IFDEF UseASM}
  2814. asm
  2815.       PUSH  EBX
  2816.       PUSH  ESI
  2817.       PUSH  EDI
  2818.       PUSH  EBP
  2819.       PUSH  ECX
  2820.       MOV   EBP,[EAX].TCipher_RC6.FRounds  // Rounds
  2821.       MOV   ESI,[EAX].TCipher_RC6.FUser    // Key
  2822.       LEA   ESI,[ESI + EBP * 8]            // Key[FRounds * 2]
  2823.       MOV   EAX,[EDX +  0]   // A
  2824.       MOV   EBX,[EDX +  4]   // B
  2825.       MOV   EDI,[EDX +  8]   // C
  2826.       MOV   EDX,[EDX + 12]   // D
  2827.       SUB   EDI,[ESI + 12]   // Dec(C, K[3])
  2828.       SUB   EAX,[ESI +  8]   // Dec(A, K[2])
  2829. @@1:  MOV   ECX,EAX          // T := A
  2830.       SUB   EDX,[ESI + 0]    // Dec(A, K[0])
  2831.       MOV   EAX,EDX          // A := D
  2832.       MOV   EDX,EDI          // D := C
  2833.       SUB   EBX,[ESI + 4]    // Dec(C, K[1])
  2834.       MOV   EDI,EBX          // C := B
  2835.       MOV   EBX,ECX          // B := T;
  2836.       LEA   ECX,[EDX * 2 +1] // ECX := D * 2 +1
  2837.       IMUL  ECX,EDX          // ECX := ECX * D
  2838.       ROL   ECX,5            // U := ROL(D * (D * 2 +1), 5)
  2839.       PUSH  ECX              // save U
  2840.       ROR   EAX,CL           // A := ROR(A - K[0], U)
  2841.       LEA   ECX,[EBX * 2 +1] // ECX := B * 2 +1
  2842.       IMUL  ECX,EBX          // ECX := ECX * B
  2843.       ROL   ECX,5            // T := ROL(B * (B * 2 +1), 5)
  2844.       XOR   EAX,ECX          // A := A xor T
  2845.       ROR   EDI,CL           // C := ROR(C - K[1], T)
  2846.       POP   ECX              // restore U
  2847.       XOR   EDI,ECX          // C := C xor U
  2848.       DEC   EBP
  2849.       LEA   ESI,[ESI - 8]    // Dec(PInteger(K), 2)
  2850.       JNZ   @@1
  2851.       SUB   EBX,[ESI + 0]    // Dec(B, K[0])
  2852.       SUB   EDX,[ESI + 4]    // Inc(D, K[1])
  2853.       POP   ECX
  2854.       MOV   [ECX +  0],EAX   // A
  2855.       MOV   [ECX +  4],EBX   // B
  2856.       MOV   [ECX +  8],EDI   // C
  2857.       MOV   [ECX + 12],EDX   // D
  2858.       POP   EBP
  2859.       POP   EDI
  2860.       POP   ESI
  2861.       POP   EBX
  2862. end;
  2863. {$ELSE}
  2864. var
  2865.   I,U,T,A,B,C,D: LongWord;
  2866.   K: PLongArray;
  2867. begin
  2868.   Assert(Size = Context.BlockSize);
  2869.  
  2870.   K := @PLongArray(FUser)[FRounds * 2];
  2871.   A := PLongArray(Source)[0] - K[2];
  2872.   B := PLongArray(Source)[1];
  2873.   C := PLongArray(Source)[2] - K[3];
  2874.   D := PLongArray(Source)[3];
  2875.   for I := 1 to FRounds do
  2876.   begin
  2877.     T := A; A := D; D := C; C := B; B := T;
  2878.     U := D * (D + D +1);
  2879.     U := U shl 5 or U shr 27;
  2880.     T := B * (B + B +1);
  2881.     T := T shl 5 or T shr 27;
  2882.     C := C - K[1];
  2883.     C := C shr T or C shl (32 - T) xor U;
  2884.     A := A - K[0];
  2885.     A := A shr U or A shl (32 - U) xor T;
  2886.     Dec(PLongWord(K), 2);
  2887.   end;
  2888.   PLongArray(Dest)[0] := A;
  2889.   PLongArray(Dest)[1] := B - K[0];
  2890.   PLongArray(Dest)[2] := C;
  2891.   PLongArray(Dest)[3] := D - K[1];
  2892. end;
  2893. {$ENDIF}
  2894.  
  2895. // .TCipher_Rijndael
  2896. const
  2897. {don't change this}
  2898.   Rijndael_Blocks =  4;
  2899.   Rijndael_Rounds = 14;
  2900.  
  2901. class function TCipher_Rijndael.Context: TCipherContext;
  2902. begin
  2903.   Result.KeySize := 32;
  2904.   Result.BlockSize := Rijndael_Blocks * 4;
  2905.   Result.BufferSize := Rijndael_Blocks * 4;
  2906.   Result.UserSize := (Rijndael_Rounds + 1) * Rijndael_Blocks * SizeOf(LongWord) * 2;
  2907.   Result.UserSave := False;
  2908. end;
  2909.  
  2910. procedure TCipher_Rijndael.DoInit(const Key; Size: Integer);
  2911. {  old Rijndael keyshedulling
  2912.  
  2913.   procedure BuildEncodeKey;
  2914.   const
  2915.     RND_Data: array[0..29] of Byte = (
  2916.       $01,$02,$04,$08,$10,$20,$40,$80,$1B,$36,$6C,$D8,$AB,$4D,$9A,
  2917.       $2F,$5E,$BC,$63,$C6,$97,$35,$6A,$D4,$B3,$7D,$FA,$EF,$C5,$91);
  2918.   var
  2919.     T,R: Integer;
  2920.  
  2921.     procedure NextRounds;
  2922.     var
  2923.       J: Integer;
  2924.     begin
  2925.       J := 0;
  2926.       while (J < FRounds -6) and (R <= FRounds) do
  2927.       begin
  2928.         while (J < FRounds -6) and (T < Rijndael_Blocks) do
  2929.         begin
  2930.           PLongArray(FUser)[R * Rijndael_Blocks + T] := K[J];
  2931.           Inc(J);
  2932.           Inc(T);
  2933.         end;
  2934.         if T = Rijndael_Blocks then
  2935.         begin
  2936.           T := 0;
  2937.           Inc(R);
  2938.         end;
  2939.       end;
  2940.     end;
  2941.  
  2942.   var
  2943.     RND: PByte;
  2944.     B: PByte;
  2945.     I: Integer;
  2946.   begin
  2947.     R := 0;
  2948.     T := 0;
  2949.     RND := @RND_Data;
  2950.     NextRounds;
  2951.     while R <= FRounds do
  2952.     begin
  2953.       B  := @K;
  2954.       B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr  8 and $FF] xor RND^; Inc(B);
  2955.       B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr 16 and $FF];          Inc(B);
  2956.       B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr 24];                  Inc(B);
  2957.       B^ := B^ xor Rijndael_S[0, K[FRounds -7] and $FF];
  2958.       Inc(RND);
  2959.       if FRounds = 14 then
  2960.       begin
  2961.         for I := 1 to 7 do K[I] := K[I] xor K[I -1];
  2962.         B  := @K[4];
  2963.         B^ := B^ xor Rijndael_S[0, K[3] and $FF];         Inc(B);
  2964.         B^ := B^ xor Rijndael_S[0, K[3] shr  8 and $FF];  Inc(B);
  2965.         B^ := B^ xor Rijndael_S[0, K[3] shr 16 and $FF];  Inc(B);
  2966.         B^ := B^ xor Rijndael_S[0, K[3] shr 24];
  2967.         for I := 5 to 7 do K[I] := K[I] xor K[I -1];
  2968.       end else
  2969.         for I := 1 to FRounds -7 do K[I] := K[I] xor K[I -1];
  2970.       NextRounds;
  2971.     end;
  2972.   end;
  2973.  
  2974.   procedure BuildDecodeKey;
  2975.   var
  2976.     I: Integer;
  2977.     D: PLongWord;
  2978.   begin
  2979.     D := Pointer(PChar(FUser) + FUserSize shr 1);
  2980.     Move(FUser^, D^, FUserSize shr 1);
  2981.     Inc(D, 4);
  2982.     for I := 0 to FRounds * 4 - 5 do
  2983.     begin
  2984.       D^ :=  Rijndael_Key[D^ and $FF] xor
  2985.             (Rijndael_Key[D^ shr  8 and $FF] shl  8 or Rijndael_Key[D^ shr  8 and $FF] shr 24) xor
  2986.             (Rijndael_Key[D^ shr 16 and $FF] shl 16 or Rijndael_Key[D^ shr 16 and $FF] shr 16) xor
  2987.             (Rijndael_Key[D^ shr 24]         shl 24 or Rijndael_Key[D^ shr 24]          shr 8);
  2988.       Inc(D);
  2989.     end;
  2990.   end; }
  2991.  
  2992. // new AES conform Keyshedulling
  2993.  
  2994.   procedure BuildEncodeKey;
  2995.   const
  2996.     RCon: array[0..9] of LongWord = ($01,$02,$04,$08,$10,$20,$40,$80,$1b,$36);
  2997.   var
  2998.     I: Integer;
  2999.     T: LongWord;
  3000.     P: PLongArray;
  3001.   begin
  3002.     P := FUser;
  3003.     if Size <= 16 then
  3004.     begin
  3005.       for I := 0 to 9 do
  3006.       begin
  3007.         T := P[3];
  3008.         P[4] := Rijndael_S[0, T shr  8 and $FF]        xor
  3009.                 Rijndael_S[0, T shr 16 and $FF] shl  8 xor
  3010.                 Rijndael_S[0, T shr 24        ] shl 16 xor
  3011.                 Rijndael_S[0, T        and $FF] shl 24 xor P[0] xor RCon[I];
  3012.         P[5] := P[1] xor P[4];
  3013.         P[6] := P[2] xor P[5];
  3014.         P[7] := P[3] xor P[6];
  3015.         P    := @P[4];
  3016.       end;
  3017.     end else
  3018.       if Size <= 24 then
  3019.       begin
  3020.         for I := 0 to 7 do
  3021.         begin
  3022.           T := P[5];
  3023.           P[6] := Rijndael_S[0, T shr  8 and $FF]        xor
  3024.                   Rijndael_S[0, T shr 16 and $FF] shl  8 xor
  3025.                   Rijndael_S[0, T shr 24        ] shl 16 xor
  3026.                   Rijndael_S[0, T        and $FF] shl 24 xor P[0] xor RCon[I];
  3027.           P[7] := P[1] xor P[6];
  3028.           P[8] := P[2] xor P[7];
  3029.           P[9] := P[3] xor P[8];
  3030.           if I = 7 then Break;
  3031.           P[10] := P[4] xor P[9];
  3032.           P[11] := P[5] xor P[10];
  3033.           P     := @P[6];
  3034.         end;
  3035.       end else
  3036.       begin
  3037.         for I :=0 to 6 do
  3038.         begin
  3039.           T := P[7];
  3040.           P[8] := Rijndael_S[0, T shr  8 and $FF]        xor
  3041.                   Rijndael_S[0, T shr 16 and $FF] shl  8 xor
  3042.                   Rijndael_S[0, T shr 24        ] shl 16 xor
  3043.                   Rijndael_S[0, T        and $FF] shl 24 xor P[0] xor RCon[I];
  3044.           P[9] := P[1] xor P[8];
  3045.           P[10] := P[2] xor P[9];
  3046.           P[11] := P[3] xor P[10];
  3047.           if I = 6 then Break;
  3048.           T := P[11];
  3049.           P[12] := Rijndael_S[0, T        and $FF]        xor
  3050.                    Rijndael_S[0, T shr  8 and $FF] shl  8 xor
  3051.                    Rijndael_S[0, T shr 16 and $FF] shl 16 xor
  3052.                    Rijndael_S[0, T shr 24        ] shl 24 xor P[4];
  3053.           P[13] := P[5] xor P[12];
  3054.           P[14] := P[6] xor P[13];
  3055.           P[15] := P[7] xor P[14];
  3056.           P     := @P[8];
  3057.         end;
  3058.       end;
  3059.   end;
  3060.  
  3061.  
  3062.   procedure BuildDecodeKey;
  3063.   var
  3064.     P: PLongWord;
  3065.     I: Integer;
  3066.   begin
  3067.     P := Pointer(PChar(FUser) + FUserSize shr 1);
  3068.     Move(FUser^, P^, FUserSize shr 1);
  3069.     Inc(P, 4);
  3070.     for I := 0 to FRounds * 4 -5 do
  3071.     begin
  3072.       P^ := Rijndael_T[4, Rijndael_S[0, P^        and $FF]] xor
  3073.             Rijndael_T[5, Rijndael_S[0, P^ shr  8 and $FF]] xor
  3074.             Rijndael_T[6, Rijndael_S[0, P^ shr 16 and $FF]] xor
  3075.             Rijndael_T[7, Rijndael_S[0, P^ shr 24        ]];
  3076.       Inc(P);
  3077.     end;
  3078.   end;
  3079.  
  3080.                                  
  3081. begin
  3082.   if Size <= 16 then FRounds := 10 else
  3083.     if Size <= 24 then FRounds := 12
  3084.       else FRounds := 14;
  3085.   FillChar(FUser^, 32, 0);      
  3086.   Move(Key, FUser^, Size);
  3087.   BuildEncodeKey;
  3088.   BuildDecodeKey;
  3089. end;
  3090.  
  3091. procedure TCipher_Rijndael.DoEncode(Source, Dest: Pointer; Size: Integer);
  3092. var
  3093.   P: PLongArray;
  3094.   I: Integer;
  3095.   A2,B2,C2,D2: LongWord;
  3096.   A1,B1,C1,D1: LongWord;
  3097. begin
  3098.   Assert(Size = Context.BlockSize);
  3099.   P  := FUser;
  3100.   A1 := PLongArray(Source)[0];
  3101.   B1 := PLongArray(Source)[1];
  3102.   C1 := PLongArray(Source)[2];
  3103.   D1 := PLongArray(Source)[3];
  3104.   for I := 2 to FRounds do
  3105.   begin
  3106.     A2 := A1 xor P[0];
  3107.     B2 := B1 xor P[1];
  3108.     C2 := C1 xor P[2];
  3109.     D2 := D1 xor P[3];
  3110.  
  3111.     A1 := Rijndael_T[0, A2        and $FF] xor
  3112.           Rijndael_T[1, B2 shr  8 and $FF] xor
  3113.           Rijndael_T[2, C2 shr 16 and $FF] xor
  3114.           Rijndael_T[3, D2 shr 24        ];
  3115.     B1 := Rijndael_T[0, B2        and $FF] xor
  3116.           Rijndael_T[1, C2 shr  8 and $FF] xor
  3117.           Rijndael_T[2, D2 shr 16 and $FF] xor
  3118.           Rijndael_T[3, A2 shr 24        ];
  3119.     C1 := Rijndael_T[0, C2        and $FF] xor
  3120.           Rijndael_T[1, D2 shr  8 and $FF] xor
  3121.           Rijndael_T[2, A2 shr 16 and $FF] xor
  3122.           Rijndael_T[3, B2 shr 24        ];
  3123.     D1 := Rijndael_T[0, D2        and $FF] xor
  3124.           Rijndael_T[1, A2 shr  8 and $FF] xor
  3125.           Rijndael_T[2, B2 shr 16 and $FF] xor
  3126.           Rijndael_T[3, C2 shr 24        ];
  3127.  
  3128.     P := @P[4];
  3129.   end;
  3130.  
  3131.   A2 := A1 xor P[0];
  3132.   B2 := B1 xor P[1];
  3133.   C2 := C1 xor P[2];
  3134.   D2 := D1 xor P[3];
  3135.  
  3136.   PLongArray(Dest)[0] := (Rijndael_S[0, A2        and $FF]        or
  3137.                           Rijndael_S[0, B2 shr  8 and $FF] shl  8 or
  3138.                           Rijndael_S[0, C2 shr 16 and $FF] shl 16 or
  3139.                           Rijndael_S[0, D2 shr 24        ] shl 24)     xor P[4];
  3140.   PLongArray(Dest)[1] := (Rijndael_S[0, B2        and $FF]        or
  3141.                           Rijndael_S[0, C2 shr  8 and $FF] shl  8 or
  3142.                           Rijndael_S[0, D2 shr 16 and $FF] shl 16 or
  3143.                           Rijndael_S[0, A2 shr 24        ] shl 24)     xor P[5];
  3144.   PLongArray(Dest)[2] := (Rijndael_S[0, C2        and $FF]        or
  3145.                           Rijndael_S[0, D2 shr  8 and $FF] shl  8 or
  3146.                           Rijndael_S[0, A2 shr 16 and $FF] shl 16 or
  3147.                           Rijndael_S[0, B2 shr 24        ] shl 24)     xor P[6];
  3148.   PLongArray(Dest)[3] := (Rijndael_S[0, D2        and $FF]        or
  3149.                           Rijndael_S[0, A2 shr  8 and $FF] shl  8 or
  3150.                           Rijndael_S[0, B2 shr 16 and $FF] shl 16 or
  3151.                           Rijndael_S[0, C2 shr 24        ] shl 24)     xor P[7];
  3152. end;
  3153.  
  3154. procedure TCipher_Rijndael.DoDecode(Source, Dest: Pointer; Size: Integer);
  3155. var
  3156.   P: PLongArray;
  3157.   I: Integer;
  3158.   A2,B2,C2,D2: LongWord;
  3159.   A1,B1,C1,D1: LongWord;
  3160. begin
  3161.   Assert(Size = Context.BlockSize);
  3162.  
  3163.   P  := Pointer(PChar(FUser) + FUserSize shr 1 + FRounds * 16);
  3164.   A1 := PLongArray(Source)[0];
  3165.   B1 := PLongArray(Source)[1];
  3166.   C1 := PLongArray(Source)[2];
  3167.   D1 := PLongArray(Source)[3];
  3168.  
  3169.   for I := 2 to FRounds do
  3170.   begin
  3171.     A2 := A1 xor P[0];
  3172.     B2 := B1 xor P[1];
  3173.     C2 := C1 xor P[2];
  3174.     D2 := D1 xor P[3];
  3175.  
  3176.     A1 := Rijndael_T[4, A2        and $FF] xor
  3177.           Rijndael_T[5, D2 shr  8 and $FF] xor
  3178.           Rijndael_T[6, C2 shr 16 and $FF] xor
  3179.           Rijndael_T[7, B2 shr 24        ];
  3180.     B1 := Rijndael_T[4, B2        and $FF] xor
  3181.           Rijndael_T[5, A2 shr  8 and $FF] xor
  3182.           Rijndael_T[6, D2 shr 16 and $FF] xor
  3183.           Rijndael_T[7, C2 shr 24        ];
  3184.     C1 := Rijndael_T[4, C2        and $FF] xor
  3185.           Rijndael_T[5, B2 shr  8 and $FF] xor
  3186.           Rijndael_T[6, A2 shr 16 and $FF] xor
  3187.           Rijndael_T[7, D2 shr 24        ];
  3188.     D1 := Rijndael_T[4, D2        and $FF] xor
  3189.           Rijndael_T[5, C2 shr  8 and $FF] xor
  3190.           Rijndael_T[6, B2 shr 16 and $FF] xor
  3191.           Rijndael_T[7, A2 shr 24        ];
  3192.  
  3193.     Dec(PLongWord(P), 4);
  3194.   end;
  3195.  
  3196.   A2 := A1 xor P[0];
  3197.   B2 := B1 xor P[1];
  3198.   C2 := C1 xor P[2];
  3199.   D2 := D1 xor P[3];
  3200.  
  3201.   Dec(PLongWord(P), 4);
  3202.  
  3203.   PLongArray(Dest)[0] := (Rijndael_S[1, A2        and $FF]        or
  3204.                           Rijndael_S[1, D2 shr  8 and $FF] shl  8 or
  3205.                           Rijndael_S[1, C2 shr 16 and $FF] shl 16 or
  3206.                           Rijndael_S[1, B2 shr 24]         shl 24)    xor P[0];
  3207.   PLongArray(Dest)[1] := (Rijndael_S[1, B2        and $FF]        or
  3208.                           Rijndael_S[1, A2 shr  8 and $FF] shl  8 or
  3209.                           Rijndael_S[1, D2 shr 16 and $FF] shl 16 or
  3210.                           Rijndael_S[1, C2 shr 24]         shl 24)    xor P[1];
  3211.   PLongArray(Dest)[2] := (Rijndael_S[1, C2        and $FF]        or
  3212.                           Rijndael_S[1, B2 shr  8 and $FF] shl  8 or
  3213.                           Rijndael_S[1, A2 shr 16 and $FF] shl 16 or
  3214.                           Rijndael_S[1, D2 shr 24]         shl 24)    xor P[2];
  3215.   PLongArray(Dest)[3] := (Rijndael_S[1, D2        and $FF]        or
  3216.                           Rijndael_S[1, C2 shr  8 and $FF] shl  8 or
  3217.                           Rijndael_S[1, B2 shr 16 and $FF] shl 16 or
  3218.                           Rijndael_S[1, A2 shr 24]         shl 24)    xor P[3];
  3219. end;
  3220.  
  3221. // .TCipher_Square
  3222. class function TCipher_Square.Context: TCipherContext;
  3223. begin
  3224.   Result.KeySize := 16;
  3225.   Result.BlockSize := 16;
  3226.   Result.BufferSize := 16;
  3227.   Result.UserSize := 9 * 4 * 2 * SizeOf(LongWord);
  3228.   Result.UserSave := False;
  3229. end;
  3230.  
  3231. procedure TCipher_Square.DoInit(const Key; Size: Integer);
  3232. type
  3233.   PSquare_Key = ^TSquare_Key;
  3234.   TSquare_Key = array[0..8, 0..3] of LongWord;
  3235. var
  3236.   E,D: PSquare_Key;
  3237.   S,T,R: LongWord;
  3238.   I,J: Integer;
  3239. begin
  3240.   E := FUser;
  3241.   D := FUser; Inc(D);
  3242.   Move(Key, E^, Size);
  3243.   for I := 1 to 8 do
  3244.   begin
  3245.     T := E[I -1, 3];
  3246.     T := T shr 8 or T shl 24;
  3247.     E[I, 0] := E[I -1, 0] xor T xor 1 shl (I - 1);
  3248.     E[I, 1] := E[I -1, 1] xor E[I, 0];
  3249.     E[I, 2] := E[I -1, 2] xor E[I, 1];
  3250.     E[I, 3] := E[I -1, 3] xor E[I, 2];
  3251.  
  3252.     D[8 -I, 0] := E[I, 0];
  3253.     D[8 -I, 1] := E[I, 1];
  3254.     D[8 -I, 2] := E[I, 2];
  3255.     D[8 -I, 3] := E[I, 3];
  3256.  
  3257.     for J := 0 to 3 do
  3258.     begin
  3259.       R := E[I -1, J];
  3260.       S := Square_PHI[R and $FF];
  3261.       T := Square_PHI[R shr  8 and $FF];
  3262.       T := T shl 8 or T shr 24;
  3263.       S := S xor T;
  3264.       T := Square_PHI[R shr 16 and $FF];
  3265.       T := T shl 16 or T shr 16;
  3266.       S := S xor T;
  3267.       T := Square_PHI[R shr 24];
  3268.       T := T shl 24 or T shr 8;
  3269.       S := S xor T;
  3270.       E[I -1, J] := S;
  3271.     end;
  3272.   end;
  3273.   D[8] := E[0];
  3274. end;
  3275.  
  3276. procedure TCipher_Square.DoEncode(Source, Dest: Pointer; Size: Integer);
  3277. var
  3278.   Key: PLongArray;
  3279.   A,B,C,D: LongWord;
  3280.   AA,BB,CC: LongWord;
  3281.   I: Integer;
  3282. begin
  3283.   Key := FUser;
  3284.   A := PLongArray(Source)[0] xor Key[0];
  3285.   B := PLongArray(Source)[1] xor Key[1];
  3286.   C := PLongArray(Source)[2] xor Key[2];
  3287.   D := PLongArray(Source)[3] xor Key[3];
  3288.   Key := @Key[4];
  3289.   for I := 0 to 6 do
  3290.   begin
  3291.     AA := Square_TE[0, A        and $FF] xor
  3292.           Square_TE[1, B        and $FF] xor
  3293.           Square_TE[2, C        and $FF] xor
  3294.           Square_TE[3, D        and $FF] xor Key[0];
  3295.     BB := Square_TE[0, A shr  8 and $FF] xor
  3296.           Square_TE[1, B shr  8 and $FF] xor
  3297.           Square_TE[2, C shr  8 and $FF] xor
  3298.           Square_TE[3, D shr  8 and $FF] xor Key[1];
  3299.     CC := Square_TE[0, A shr 16 and $FF] xor
  3300.           Square_TE[1, B shr 16 and $FF] xor
  3301.           Square_TE[2, C shr 16 and $FF] xor
  3302.           Square_TE[3, D shr 16 and $FF] xor Key[2];
  3303.     D  := Square_TE[0, A shr 24        ] xor
  3304.           Square_TE[1, B shr 24        ] xor
  3305.           Square_TE[2, C shr 24        ] xor
  3306.           Square_TE[3, D shr 24        ] xor Key[3];
  3307.  
  3308.     A := AA; B := BB; C := CC;
  3309.  
  3310.     Key := @Key[4];
  3311.   end;
  3312.  
  3313.   PLongArray(Dest)[0] := LongWord(Square_SE[A        and $FF])        xor
  3314.                          LongWord(Square_SE[B        and $FF]) shl  8 xor
  3315.                          LongWord(Square_SE[C        and $FF]) shl 16 xor
  3316.                          LongWord(Square_SE[D        and $FF]) shl 24 xor Key[0];
  3317.   PLongArray(Dest)[1] := LongWord(Square_SE[A shr  8 and $FF])        xor
  3318.                          LongWord(Square_SE[B shr  8 and $FF]) shl  8 xor
  3319.                          LongWord(Square_SE[C shr  8 and $FF]) shl 16 xor
  3320.                          LongWord(Square_SE[D shr  8 and $FF]) shl 24 xor Key[1];
  3321.   PLongArray(Dest)[2] := LongWord(Square_SE[A shr 16 and $FF])        xor
  3322.                          LongWord(Square_SE[B shr 16 and $FF]) shl  8 xor
  3323.                          LongWord(Square_SE[C shr 16 and $FF]) shl 16 xor
  3324.                          LongWord(Square_SE[D shr 16 and $FF]) shl 24 xor Key[2];
  3325.   PLongArray(Dest)[3] := LongWord(Square_SE[A shr 24        ])        xor
  3326.                          LongWord(Square_SE[B shr 24        ]) shl  8 xor
  3327.                          LongWord(Square_SE[C shr 24        ]) shl 16 xor
  3328.                          LongWord(Square_SE[D shr 24        ]) shl 24 xor Key[3];
  3329. end;
  3330.  
  3331. procedure TCipher_Square.DoDecode(Source, Dest: Pointer; Size: Integer);
  3332. var
  3333.   Key: PLongArray;
  3334.   A,B,C,D: LongWord;
  3335.   AA,BB,CC: LongWord;
  3336.   I: Integer;
  3337. begin
  3338.   Key := @PLongArray(FUser)[9 * 4];
  3339.   A := PLongArray(Source)[0] xor Key[0];
  3340.   B := PLongArray(Source)[1] xor Key[1];
  3341.   C := PLongArray(Source)[2] xor Key[2];
  3342.   D := PLongArray(Source)[3] xor Key[3];
  3343.   Key := @Key[4];
  3344.   for I := 0 to 6 do
  3345.   begin
  3346.     AA := Square_TD[0, A        and $FF] xor
  3347.           Square_TD[1, B        and $FF] xor
  3348.           Square_TD[2, C        and $FF] xor
  3349.           Square_TD[3, D        and $FF] xor Key[0];
  3350.     BB := Square_TD[0, A shr  8 and $FF] xor
  3351.           Square_TD[1, B shr  8 and $FF] xor
  3352.           Square_TD[2, C shr  8 and $FF] xor
  3353.           Square_TD[3, D shr  8 and $FF] xor Key[1];
  3354.     CC := Square_TD[0, A shr 16 and $FF] xor
  3355.           Square_TD[1, B shr 16 and $FF] xor
  3356.           Square_TD[2, C shr 16 and $FF] xor
  3357.           Square_TD[3, D shr 16 and $FF] xor Key[2];
  3358.     D  := Square_TD[0, A shr 24        ] xor
  3359.           Square_TD[1, B shr 24        ] xor
  3360.           Square_TD[2, C shr 24        ] xor
  3361.           Square_TD[3, D shr 24        ] xor Key[3];
  3362.  
  3363.     A := AA; B := BB; C := CC;
  3364.     Key := @Key[4];
  3365.   end;
  3366.  
  3367.   PLongArray(Dest)[0] := LongWord(Square_SD[A        and $FF])        xor
  3368.                          LongWord(Square_SD[B        and $FF]) shl  8 xor
  3369.                          LongWord(Square_SD[C        and $FF]) shl 16 xor
  3370.                          LongWord(Square_SD[D        and $FF]) shl 24 xor Key[0];
  3371.   PLongArray(Dest)[1] := LongWord(Square_SD[A shr  8 and $FF])        xor
  3372.                          LongWord(Square_SD[B shr  8 and $FF]) shl  8 xor
  3373.                          LongWord(Square_SD[C shr  8 and $FF]) shl 16 xor
  3374.                          LongWord(Square_SD[D shr  8 and $FF]) shl 24 xor Key[1];
  3375.   PLongArray(Dest)[2] := LongWord(Square_SD[A shr 16 and $FF])        xor
  3376.                          LongWord(Square_SD[B shr 16 and $FF]) shl  8 xor
  3377.                          LongWord(Square_SD[C shr 16 and $FF]) shl 16 xor
  3378.                          LongWord(Square_SD[D shr 16 and $FF]) shl 24 xor Key[2];
  3379.   PLongArray(Dest)[3] := LongWord(Square_SD[A shr 24        ])        xor
  3380.                          LongWord(Square_SD[B shr 24        ]) shl  8 xor
  3381.                          LongWord(Square_SD[C shr 24        ]) shl 16 xor
  3382.                          LongWord(Square_SD[D shr 24        ]) shl 24 xor Key[3];
  3383. end;
  3384.  
  3385. // .TCipher_SCOP
  3386. class function TCipher_SCOP.Context: TCipherContext;
  3387. begin
  3388.   Result.KeySize := 48;
  3389.   Result.BlockSize := 4;
  3390.   Result.BufferSize := 32;
  3391.   Result.UserSize := 384 * 4 + 3 * SizeOf(LongWord);
  3392.   Result.UserSave := True;
  3393. end;
  3394.  
  3395. procedure TCipher_SCOP.DoInit(const Key; Size: Integer);
  3396. var
  3397.   Init_State: packed record
  3398.                 Coef: array[0..7, 0..3] of Byte;
  3399.                 X: array[0..3] of LongWord;
  3400.               end;
  3401.  
  3402.   procedure ExpandKey;
  3403.   var
  3404.     P: PByteArray;
  3405.     I,C: Integer;
  3406.   begin
  3407.     C := 1;
  3408.     P := @Init_State;
  3409.     Move(Key, P^, Size);
  3410.     for I := Size to 47 do P[I] := P[I - Size] + P[I - Size +1];
  3411.     for I := 0 to 31 do
  3412.       if P[I] = 0 then
  3413.       begin
  3414.         P[I] := C;
  3415.         Inc(C);
  3416.       end;
  3417.   end;
  3418.  
  3419.   procedure GP8(Data: PLongArray);
  3420.   var
  3421.     I,I2: Integer;
  3422.     NewX: array[0..3] of LongWord;
  3423.     X1,X2,X3,X4: LongWord;
  3424.     Y1,Y2: LongWord;
  3425.   begin
  3426.     I := 0;
  3427.     I2 := 0;
  3428.     while I < 8 do
  3429.     begin
  3430.       X1 := Init_State.X[I2] shr 16;
  3431.       X2 := X1 * X1;
  3432.       X3 := X2 * X1;
  3433.       X4 := X3 * X1;
  3434.       Y1 := Init_State.Coef[I][0] * X4 +
  3435.             Init_State.Coef[I][1] * X3 +
  3436.             Init_State.Coef[I][2] * X2 +
  3437.             Init_State.Coef[I][3] * X1 + 1;
  3438.       X1 := Init_State.X[I2] and $FFFF;
  3439.       X2 := X1 * X1;
  3440.       X3 := X2 * X1;
  3441.       X4 := X3 * X1;
  3442.       Y2 := Init_State.Coef[I +1][0] * X4 +
  3443.             Init_State.Coef[I +2][1] * X3 +
  3444.             Init_State.Coef[I +3][2] * X2 +
  3445.             Init_State.Coef[I +4][3] * X1 + 1;
  3446.       Data[I2] := Y1 shl 16 or Y2 and $FFFF;
  3447.       NewX[I2] := Y1 and $FFFF0000 or Y2 shr 16;
  3448.       Inc(I2);
  3449.       Inc(I, 2);
  3450.     end;
  3451.     Init_State.X[0] := NewX[0] shr 16 or NewX[3] shl 16;
  3452.     Init_State.X[1] := NewX[0] shl 16 or NewX[1] shr 16;
  3453.     Init_State.X[2] := NewX[1] shl 16 or NewX[2] shr 16;
  3454.     Init_State.X[3] := NewX[2] shl 16 or NewX[3] shr 16;
  3455.   end;
  3456.  
  3457. var
  3458.   I,J: Integer;
  3459.   T: array[0..3] of Integer;
  3460.   P: PLongArray;
  3461. begin
  3462.   FillChar(Init_State, SizeOf(Init_State), 0);
  3463.   FillChar(T, SizeOf(T), 0);
  3464.   P := Pointer(PChar(FUser) + 12);
  3465.   ExpandKey;
  3466.   for I := 0 to 7 do GP8(@T);
  3467.   for I := 0 to 11 do
  3468.   begin
  3469.     for J := 0 to 7 do GP8(@P[I * 32 + J * 4]);
  3470.     GP8(@T);
  3471.   end;
  3472.   GP8(@T);
  3473.   I := T[3] and $7F;
  3474.   P[I + 3] := P[I + 3] or 1;
  3475.   P := FUser;
  3476.   P[0] := T[3] shr 24 and $FF;
  3477.   P[1] := T[3] shr 16 and $FF;
  3478.   P[2] := T[3] shr  8 and $FF;
  3479.   ProtectBuffer(Init_State, SizeOf(Init_State));
  3480. end;
  3481.  
  3482. procedure TCipher_SCOP.DoEncode(Source, Dest: Pointer; Size: Integer);
  3483. var
  3484.   I,J: Byte;
  3485.   T2,T3,T1: LongWord;
  3486.   P: PLongArray;
  3487.   W: Integer;
  3488. begin
  3489.   P  := FUser;
  3490.   I  := P[0];
  3491.   J  := P[1];
  3492.   T3 := P[2];
  3493.   for W := 0 to Size div 4 -1 do
  3494.   begin
  3495.     T1 := P[J + 3 + 128]; Inc(J, T3);
  3496.     T2 := P[J + 3 + 128];
  3497.     PLongArray(Dest)[W] := PLongArray(Source)[W] + T1 + T2;
  3498.     T3 := T2 + P[I + 3];  Inc(I);
  3499.     P[J + 3 + 128] := T3;
  3500.     Inc(J, T2);
  3501.   end;
  3502.   P[0] := I;
  3503.   P[1] := J;
  3504.   P[2] := T3;
  3505. end;
  3506.  
  3507. procedure TCipher_SCOP.DoDecode(Source, Dest: Pointer; Size: Integer);
  3508. var
  3509.   I, J: Byte;
  3510.   T1,T2,T3: LongWord;
  3511.   P: PLongArray;
  3512.   W: Integer;
  3513. begin
  3514.   P  := FUser;
  3515.   I  := P[0];
  3516.   J  := P[1];
  3517.   T3 := P[2];
  3518.   for W := 0 to Size div 4 -1 do
  3519.   begin
  3520.     T1 := P[J + 3 + 128]; Inc(J, T3);
  3521.     T2 := P[J + 3 + 128];
  3522.     PLongArray(Dest)[W] := PLongArray(Source)[W] - T1 - T2;
  3523.     T3 := T2 + P[I + 3];
  3524.     Inc(I);
  3525.     P[J + 3 + 128] := T3;
  3526.     Inc(J, T2);
  3527.   end;
  3528.   P[0] := I;
  3529.   P[1] := J;
  3530.   P[2] := T3;
  3531. end;
  3532.  
  3533.  
  3534. // .TCipher_Sapphire
  3535. type
  3536.   PSapphireKey = ^TSapphireKey;
  3537.   TSapphireKey = packed record
  3538.                    Cards: array[0..255] of LongWord;
  3539.                    Rotor: LongWord;
  3540.                    Ratchet: LongWord;
  3541.                    Avalanche: LongWord;
  3542.                    Plain: LongWord;
  3543.                    Cipher: LongWord;
  3544.                  end;
  3545.                  
  3546. class function TCipher_Sapphire.Context: TCipherContext;
  3547. begin
  3548.   Result.KeySize := 1024;
  3549.   Result.BlockSize := 1;
  3550.   Result.BufferSize := 32;
  3551.   Result.UserSize := SizeOf(TSapphireKey);
  3552.   Result.UserSave := True;
  3553. end;
  3554.  
  3555. procedure TCipher_Sapphire.DoInit(const Key; Size: Integer);
  3556. var
  3557.   Sum: Byte;
  3558.   P: Integer;
  3559.  
  3560.   function KeyRand(Max: LongWord): Byte;
  3561.   var
  3562.     I,M: LongWord;
  3563.   begin
  3564.     Result := 0;
  3565.     if Max = 0 then Exit;
  3566.     I := 0;
  3567.     M := 1;
  3568.     while M < Max do
  3569.      Inc(M, M or 1);
  3570.     repeat
  3571.       Inc(Sum, TByteArray(Key)[P]);
  3572.       Inc(P);
  3573.       if P >= Size then
  3574.       begin
  3575.         P := 0;
  3576.         Inc(Sum, Size);
  3577.       end;
  3578.       Result := M and Sum;
  3579.       Inc(I);
  3580.       if I > 11 then Result := Result mod Max;
  3581.     until Result <= Max;
  3582.   end;
  3583.  
  3584. var
  3585.   I,S,T: Integer;
  3586. begin
  3587.   with PSapphireKey(FUser)^ do
  3588.     if Size <= 0 then
  3589.     begin
  3590.       Rotor := 1;
  3591.       Ratchet := 3;
  3592.       Avalanche := 5;
  3593.       Plain := 7;
  3594.       Cipher := 11;
  3595.       for I := 0 to 255 do Cards[I] := 255 - I;
  3596.     end else
  3597.     begin
  3598.       for I := 0 to 255 do Cards[I] := I;
  3599.       P   := 0;
  3600.       Sum := 0;
  3601.       for I := 255 downto 1 do
  3602.       begin
  3603.         S := KeyRand(I);
  3604.         T := Cards[I];
  3605.         Cards[I] := Cards[S];
  3606.         Cards[S] := T;
  3607.       end;
  3608.       Rotor := Cards[1];
  3609.       Ratchet := Cards[3];
  3610.       Avalanche := Cards[5];
  3611.       Plain := Cards[7];
  3612.       Cipher := Cards[Sum];
  3613.     end;
  3614. end;
  3615.  
  3616. procedure TCipher_Sapphire.DoEncode(Source, Dest: Pointer; Size: Integer);
  3617. var
  3618.   T: LongWord;
  3619.   I: Integer;
  3620. begin
  3621.   with PSapphireKey(FUser)^ do
  3622.     for I := 0 to Size -1 do
  3623.     begin
  3624.       Ratchet := (Ratchet + Cards[Rotor]) and $FF;
  3625.       Rotor := (Rotor + 1) and $FF;
  3626.       T := Cards[Cipher];
  3627.       Cards[Cipher] := Cards[Ratchet];
  3628.       Cards[Ratchet] := Cards[Plain];
  3629.       Cards[Plain] := Cards[Rotor];
  3630.       Cards[Rotor] := T;
  3631.       Avalanche := (Avalanche + Cards[T]) and $FF;
  3632.       T := (Cards[Plain] + Cards[Cipher] + Cards[Avalanche]) and $FF;
  3633.       Plain := PByteArray(Source)[I];
  3634.       Cipher := Plain xor Cards[Cards[T]] xor Cards[(Cards[Ratchet] + Cards[Rotor]) and $FF];
  3635.       PByteArray(Dest)[I] := Cipher;
  3636.     end;
  3637. end;
  3638.  
  3639. procedure TCipher_Sapphire.DoDecode(Source, Dest: Pointer; Size: Integer);
  3640. var
  3641.   T: LongWord;
  3642.   I: Integer;
  3643. begin
  3644.   with PSapphireKey(FUser)^ do
  3645.     for I := 0 to Size -1 do
  3646.     begin
  3647.       Ratchet := (Ratchet + Cards[Rotor]) and $FF;
  3648.       Rotor := (Rotor + 1) and $FF;
  3649.       T := Cards[Cipher];
  3650.       Cards[Cipher] := Cards[Ratchet];
  3651.       Cards[Ratchet] := Cards[Plain];
  3652.       Cards[Plain] := Cards[Rotor];
  3653.       Cards[Rotor] := T;
  3654.       Avalanche := (Avalanche + Cards[T]) and $FF;
  3655.       T := (Cards[Plain] + Cards[Cipher] + Cards[Avalanche]) and $FF;
  3656.       Cipher := PByteArray(Source)[I];
  3657.       Plain := Cipher xor Cards[Cards[T]] xor Cards[(Cards[Ratchet] + Cards[Rotor]) and $FF];
  3658.       PByteArray(Dest)[I] := Plain;
  3659.     end;
  3660. end;
  3661.  
  3662. // .DES
  3663. procedure DES_Func(Source, Dest, Key: PLongArray);
  3664. var
  3665.   L,R,X,Y,I: LongWord;
  3666. begin
  3667.   L := SwapLong(Source[0]);
  3668.   R := SwapLong(Source[1]);
  3669.  
  3670.   X := (L shr  4 xor R) and $0F0F0F0F; R := R xor X; L := L xor X shl  4;
  3671.   X := (L shr 16 xor R) and $0000FFFF; R := R xor X; L := L xor X shl 16;
  3672.   X := (R shr  2 xor L) and $33333333; L := L xor X; R := R xor X shl  2;
  3673.   X := (R shr  8 xor L) and $00FF00FF; L := L xor X; R := R xor X shl  8;
  3674.  
  3675.   R := R shl 1 or R shr 31;
  3676.   X := (L xor R) and $AAAAAAAA;
  3677.   R := R xor X;
  3678.   L := L xor X;
  3679.   L := L shl 1 or L shr 31;
  3680.  
  3681.   for I := 0 to 7 do
  3682.   begin
  3683.     X := (R shl 28 or R shr 4) xor Key[0];
  3684.     Y := R xor Key[1];
  3685.     L := L xor (DES_Data[0, X        and $3F] or DES_Data[1, X shr  8 and $3F] or
  3686.                 DES_Data[2, X shr 16 and $3F] or DES_Data[3, X shr 24 and $3F] or
  3687.                 DES_Data[4, Y        and $3F] or DES_Data[5, Y shr  8 and $3F] or
  3688.                 DES_Data[6, Y shr 16 and $3F] or DES_Data[7, Y shr 24 and $3F]);
  3689.  
  3690.     X := (L shl 28 or L shr 4) xor Key[2];
  3691.     Y := L xor Key[3];
  3692.     R := R xor (DES_Data[0, X        and $3F] or DES_Data[1, X shr  8 and $3F] or
  3693.                 DES_Data[2, X shr 16 and $3F] or DES_Data[3, X shr 24 and $3F] or
  3694.                 DES_Data[4, Y        and $3F] or DES_Data[5, Y shr  8 and $3F] or
  3695.                 DES_Data[6, Y shr 16 and $3F] or DES_Data[7, Y shr 24 and $3F]);
  3696.     Key := @Key[4];            
  3697.   end;
  3698.  
  3699.   R := R shl 31 or R shr 1;
  3700.   X := (L xor R) and $AAAAAAAA;
  3701.   R := R xor X;
  3702.   L := L xor X;
  3703.   L := L shl 31 or L shr 1;
  3704.  
  3705.   X := (L shr  8 xor R) and $00FF00FF; R := R xor X; L := L xor X shl  8;
  3706.   X := (L shr  2 xor R) and $33333333; R := R xor X; L := L xor X shl  2;
  3707.   X := (R shr 16 xor L) and $0000FFFF; L := L xor X; R := R xor X shl 16;
  3708.   X := (R shr  4 xor L) and $0F0F0F0F; L := L xor X; R := R xor X shl  4;
  3709.  
  3710.   Dest[0] := SwapLong(R);
  3711.   Dest[1] := SwapLong(L);
  3712. end;
  3713.  
  3714. // .TCipher_1DES
  3715. class function TCipher_1DES.Context: TCipherContext;
  3716. begin
  3717.   Result.KeySize := 8;
  3718.   Result.BlockSize := 8;
  3719.   Result.BufferSize := 8;
  3720.   Result.UserSize := 32 * 4 * 2;
  3721.   Result.UserSave := False;
  3722. end;
  3723.  
  3724. procedure TCipher_1DES.DoInitKey(const Data: array of Byte; Key: PLongArray; Reverse: Boolean);
  3725. const
  3726.   ROT: array[0..15] of Byte = (1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28);
  3727. var
  3728.   I,J,L,M,N: LongWord;
  3729.   PC_M,PC_R: array[0..55] of Byte;
  3730.   K: array[0..31] of LongWord;
  3731. begin
  3732.   FillChar(K, SizeOf(K), 0);
  3733.   for I := 0 to 55 do
  3734.     if Data[DES_PC1[I] shr 3] and ($80 shr (DES_PC1[I] and $07)) <> 0 then PC_M[I] := 1
  3735.       else PC_M[I] := 0;
  3736.   for I := 0 to 15 do
  3737.   begin
  3738.     if Reverse then M := (15 - I) shl 1
  3739.       else M := I shl 1;
  3740.     N := M + 1;
  3741.     for J := 0 to 27 do
  3742.     begin
  3743.       L := J + ROT[I];
  3744.       if L < 28 then PC_R[J] := PC_M[L] else PC_R[J] := PC_M[L - 28];
  3745.     end;
  3746.     for J := 28 to 55 do
  3747.     begin
  3748.       L := J + ROT[I];
  3749.       if L < 56 then PC_R[J] := PC_M[L] else PC_R[J] := PC_M[L - 28];
  3750.     end;
  3751.     L := $1000000;
  3752.     for J := 0 to 23 do
  3753.     begin
  3754.       L := L shr 1;
  3755.       if PC_R[DES_PC2[J     ]] <> 0 then K[M] := K[M] or L;
  3756.       if PC_R[DES_PC2[J + 24]] <> 0 then K[N] := K[N] or L;
  3757.     end;
  3758.   end;
  3759.   for I := 0 to 15 do
  3760.   begin
  3761.     M := I shl 1;
  3762.     N := M + 1;
  3763.     Key[0] := K[M] and $00FC0000 shl  6 or
  3764.               K[M] and $00000FC0 shl 10 or
  3765.               K[N] and $00FC0000 shr 10 or
  3766.               K[N] and $00000FC0 shr  6;
  3767.     Key[1] := K[M] and $0003F000 shl 12 or
  3768.               K[M] and $0000003F shl 16 or
  3769.               K[N] and $0003F000 shr  4 or
  3770.               K[N] and $0000003F;
  3771.     Key := @Key[2];
  3772.   end;
  3773.   ProtectBuffer(K, SizeOf(K));
  3774.   ProtectBuffer(PC_M, SizeOf(PC_M));
  3775.   ProtectBuffer(PC_R, SizeOf(PC_R));
  3776. end;
  3777.  
  3778. procedure TCipher_1DES.DoInit(const Key; Size: Integer);
  3779. var
  3780.   K: array[0..7] of Byte;
  3781. begin
  3782.   FillChar(K, SizeOf(K), 0);
  3783.   Move(Key, K, Size);
  3784.   DoInitKey(K, FUser, False);
  3785.   DoInitKey(K, @PLongArray(FUser)[32], True);
  3786.   ProtectBuffer(K, SizeOf(K));
  3787. end;
  3788.  
  3789. procedure TCipher_1DES.DoEncode(Source, Dest: Pointer; Size: Integer);
  3790. begin
  3791.   Assert(Size = Context.BufferSize);
  3792.   DES_Func(Source, Dest, FUser);
  3793. end;
  3794.  
  3795. procedure TCipher_1DES.DoDecode(Source, Dest: Pointer; Size: Integer);
  3796. begin
  3797.   Assert(Size = Context.BufferSize);
  3798.   DES_Func(Source,Dest, @PLongArray(FUser)[32]);
  3799. end;
  3800.  
  3801. // .TCipher_2DES
  3802. class function TCipher_2DES.Context: TCipherContext;
  3803. begin
  3804.   Result.KeySize := 16;
  3805.   Result.BlockSize := 8;
  3806.   Result.BufferSize := 8;
  3807.   Result.UserSize := 32 * 4 * 2 * 2;
  3808.   Result.UserSave := False;
  3809. end;
  3810.  
  3811. procedure TCipher_2DES.DoInit(const Key; Size: Integer);
  3812. var
  3813.   K: array[0..15] of Byte;
  3814.   P: PLongArray;
  3815. begin
  3816.   FillChar(K, SizeOf(K), 0);
  3817.   Move(Key, K, Size);
  3818.   P := FUser;
  3819.   DoInitKey(K[0], @P[ 0], False);
  3820.   DoInitKey(K[8], @P[32], True);
  3821.   DoInitKey(K[0], @P[64], True);
  3822.   DoInitKey(K[8], @P[96], False);
  3823.   ProtectBuffer(K, SizeOf(K));
  3824. end;
  3825.  
  3826. procedure TCipher_2DES.DoEncode(Source, Dest: Pointer; Size: Integer);
  3827. begin
  3828.   Assert(Size = Context.BufferSize);
  3829.   DES_Func(Source, Dest, FUser);
  3830.   DES_Func(Source, Dest, @PLongArray(FUser)[32]);
  3831.   DES_Func(Source, Dest, FUser);
  3832. end;
  3833.  
  3834. procedure TCipher_2DES.DoDecode(Source, Dest: Pointer; Size: Integer);
  3835. begin
  3836.   Assert(Size = Context.BufferSize);
  3837.   DES_Func(Source, Dest, @PLongArray(FUser)[64]);
  3838.   DES_Func(Source, Dest, @PLongArray(FUser)[96]);
  3839.   DES_Func(Source, Dest, @PLongArray(FUser)[64]);
  3840. end;
  3841.  
  3842. // .TCipher_3DES
  3843. class function TCipher_3DES.Context: TCipherContext;
  3844. begin
  3845.   Result.KeySize := 24;
  3846.   Result.BlockSize := 8;
  3847.   Result.BufferSize := 8;
  3848.   Result.UserSize := 32 * 4 * 2 * 3;
  3849.   Result.UserSave := False;
  3850. end;
  3851.  
  3852. procedure TCipher_3DES.DoInit(const Key; Size: Integer);
  3853. var
  3854.   K: array[0..23] of Byte;
  3855.   P: PLongArray;
  3856. begin
  3857.   FillChar(K, SizeOf(K), 0);
  3858.   Move(Key, K, Size);
  3859.   P := FUser;
  3860.   DoInitKey(K[ 0], @P[  0], False);
  3861.   DoInitKey(K[ 8], @P[ 32], True);
  3862.   DoInitKey(K[16], @P[ 64], False);
  3863.   DoInitKey(K[16], @P[ 96], True);
  3864.   DoInitKey(K[ 8], @P[128], False);
  3865.   DoInitKey(K[ 0], @P[160], True);
  3866.   ProtectBuffer(K, SizeOf(K));
  3867. end;
  3868.  
  3869. procedure TCipher_3DES.DoEncode(Source, Dest: Pointer; Size: Integer);
  3870. begin
  3871.   Assert(Size = Context.BufferSize);
  3872.   DES_Func(Source, Dest, @PLongArray(FUser)[ 0]);
  3873.   DES_Func(Source, Dest, @PLongArray(FUser)[32]);
  3874.   DES_Func(Source, Dest, @PLongArray(FUser)[64]);
  3875. end;
  3876.  
  3877. procedure TCipher_3DES.DoDecode(Source, Dest: Pointer; Size: Integer);
  3878. begin
  3879.   Assert(Size = Context.BufferSize);
  3880.   DES_Func(Source, Dest, @PLongArray(FUser)[96]);
  3881.   DES_Func(Source, Dest, @PLongArray(FUser)[128]);
  3882.   DES_Func(Source, Dest, @PLongArray(FUser)[160]);
  3883. end;
  3884.  
  3885. // .TCipher_2DDES
  3886. class function TCipher_2DDES.Context: TCipherContext;
  3887. begin
  3888.   Result := inherited Context;
  3889.   Result.BlockSize := 16;
  3890.   Result.BufferSize := 16;
  3891. end;
  3892.  
  3893. procedure TCipher_2DDES.DoEncode(Source, Dest: Pointer; Size: Integer);
  3894. var
  3895.   T: LongWord;
  3896.   S: PLongArray absolute Source;
  3897.   D: PLongArray absolute Dest;
  3898. begin
  3899.   Assert(Size = Context.BufferSize);
  3900.  
  3901.   DES_Func(@S[0], @D[0], FUser);
  3902.   DES_Func(@S[2], @D[2], FUser);
  3903.   T := D[1]; D[1] := D[2]; D[2] := T;
  3904.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]);
  3905.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]);
  3906.   T := D[1]; D[1] := D[2]; D[2] := T;
  3907.   DES_Func(@D[0], @D[0], FUser);
  3908.   DES_Func(@D[2], @D[2], FUser);
  3909. end;
  3910.  
  3911. procedure TCipher_2DDES.DoDecode(Source, Dest: Pointer; Size: Integer);
  3912. var
  3913.   T: LongWord;
  3914.   S: PLongArray absolute Source;
  3915.   D: PLongArray absolute Dest;
  3916. begin
  3917.   Assert(Size = Context.BufferSize);
  3918.  
  3919.   DES_Func(@S[0], @D[0], @PLongArray(FUser)[64]);
  3920.   DES_Func(@S[2], @D[2], @PLongArray(FUser)[64]);
  3921.   T := D[1]; D[1] := D[2]; D[2] := T;
  3922.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[96]);
  3923.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[96]);
  3924.   T := D[1]; D[1] := D[2]; D[2] := T;
  3925.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]);
  3926.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]);
  3927. end;
  3928.  
  3929. // .TCipher_3DDES
  3930. class function TCipher_3DDES.Context: TCipherContext;
  3931. begin
  3932.   Result := inherited Context;
  3933.   Result.BlockSize := 16;
  3934.   Result.BufferSize := 16;
  3935. end;
  3936.  
  3937. procedure TCipher_3DDES.DoEncode(Source, Dest: Pointer; Size: Integer);
  3938. var
  3939.   T: LongWord;
  3940.   S: PLongArray absolute Source;
  3941.   D: PLongArray absolute Dest;
  3942. begin
  3943.   Assert(Size = Context.BufferSize);
  3944.  
  3945.   DES_Func(@S[0], @D[0], FUser);
  3946.   DES_Func(@S[2], @D[2], FUser);
  3947.   T := D[1]; D[1] := D[2]; D[2] := T;
  3948.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]);
  3949.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]);
  3950.   T := D[1]; D[1] := D[2]; D[2] := T;
  3951.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]);
  3952.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]);
  3953. end;
  3954.  
  3955. procedure TCipher_3DDES.DoDecode(Source, Dest: Pointer; Size: Integer);
  3956. var
  3957.   T: LongWord;
  3958.   S: PLongArray absolute Source;
  3959.   D: PLongArray absolute Dest;
  3960. begin
  3961.   Assert(Size = Context.BufferSize);
  3962.  
  3963.   DES_Func(@S[0], @D[0], @PLongArray(FUser)[96]);
  3964.   DES_Func(@S[2], @D[2], @PLongArray(FUser)[96]);
  3965.   T := D[1]; D[1] := D[2]; D[2] := T;
  3966.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[128]);
  3967.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[128]);
  3968.   T := D[1]; D[1] := D[2]; D[2] := T;
  3969.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[160]);
  3970.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[160]);
  3971. end;
  3972.  
  3973.  
  3974. // .TCipher_3TDES
  3975. class function TCipher_3TDES.Context: TCipherContext;
  3976. begin
  3977.   Result := inherited Context;
  3978.   Result.BlockSize := 24;
  3979.   Result.BufferSize := 24;
  3980. end;
  3981.  
  3982. procedure TCipher_3TDES.DoEncode(Source, Dest: Pointer; Size: Integer);
  3983. var
  3984.   T: LongWord;
  3985.   S: PLongArray absolute Source;
  3986.   D: PLongArray absolute Dest;
  3987. begin
  3988.   Assert(Size = Context.BufferSize);
  3989.  
  3990.   DES_Func(@S[0], @D[0], FUser);
  3991.   DES_Func(@S[2], @D[2], FUser);
  3992.   DES_Func(@S[4], @D[4], FUser);
  3993.   T := D[1]; D[1] := D[2]; D[2] := T;
  3994.   T := D[3]; D[3] := D[4]; D[4] := T;
  3995.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]);
  3996.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]);
  3997.   DES_Func(@D[4], @D[4], @PLongArray(FUser)[32]);
  3998.   T := D[1]; D[1] := D[2]; D[2] := T;
  3999.   T := D[3]; D[3] := D[4]; D[4] := T;
  4000.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]);
  4001.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]);
  4002.   DES_Func(@D[4], @D[4], @PLongArray(FUser)[64]);
  4003. end;
  4004.  
  4005. procedure TCipher_3TDES.DoDecode(Source, Dest: Pointer; Size: Integer);
  4006. var
  4007.   T: LongWord;
  4008.   S: PLongArray absolute Source;
  4009.   D: PLongArray absolute Dest;
  4010. begin
  4011.   Assert(Size = Context.BufferSize);
  4012.  
  4013.   DES_Func(@S[0], @D[0], @PLongArray(FUser)[96]);
  4014.   DES_Func(@S[2], @D[2], @PLongArray(FUser)[96]);
  4015.   DES_Func(@S[4], @D[4], @PLongArray(FUser)[96]);
  4016.   T := D[1]; D[1] := D[2]; D[2] := T;
  4017.   T := D[3]; D[3] := D[4]; D[4] := T;
  4018.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[128]);
  4019.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[128]);
  4020.   DES_Func(@D[4], @D[4], @PLongArray(FUser)[128]);
  4021.   T := D[1]; D[1] := D[2]; D[2] := T;
  4022.   T := D[3]; D[3] := D[4]; D[4] := T;
  4023.   DES_Func(@D[0], @D[0], @PLongArray(FUser)[160]);
  4024.   DES_Func(@D[2], @D[2], @PLongArray(FUser)[160]);
  4025.   DES_Func(@D[4], @D[4], @PLongArray(FUser)[160]);
  4026. end;
  4027.  
  4028.  
  4029. // .TCipher_3Way
  4030. type
  4031.   P3Way_Key = ^T3Way_Key;
  4032.   T3Way_Key = packed record
  4033.                 E_Key: array[0..2] of LongWord;
  4034.                 E_Data: array[0..11] of LongWord;
  4035.                 D_Key: array[0..2] of LongWord;
  4036.                 D_Data: array[0..11] of LongWord;
  4037.               end;
  4038.  
  4039. class function TCipher_3Way.Context: TCipherContext;
  4040. begin
  4041.   Result.KeySize := 12;
  4042.   Result.BlockSize := 12;
  4043.   Result.BufferSize := 12;
  4044.   Result.UserSize := SizeOf(T3Way_Key);
  4045.   Result.UserSave := False;
  4046. end;
  4047.  
  4048. procedure TCipher_3Way.DoInit(const Key; Size: Integer);
  4049.  
  4050.   procedure RANDGenerate(Start: LongWord; var P: Array of LongWord);
  4051.   var
  4052.     I: Integer;
  4053.   begin
  4054.     for I := 0 to 11 do
  4055.     begin
  4056.       P[I] := Start;
  4057.       Start := Start shl 1;
  4058.       if Start and $10000 <> 0 then Start := Start xor $11011;
  4059.     end;
  4060.   end;
  4061.  
  4062. var
  4063.   A0,A1,A2: LongWord;
  4064.   B0,B1,B2: LongWord;
  4065. begin
  4066.   with P3Way_Key(FUser)^ do
  4067.   begin
  4068.     Move(Key, E_Key, Size);
  4069.     Move(Key, D_Key, Size);
  4070.     RANDGenerate($0B0B, E_Data);
  4071.     RANDGenerate($B1B1, D_Data);
  4072.     A0 := D_Key[0];
  4073.     A1 := D_Key[1];
  4074.     A2 := D_Key[2];
  4075.     B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
  4076.                  A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
  4077.                  A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
  4078.     B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
  4079.                  A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
  4080.                  A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
  4081.     B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
  4082.                  A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
  4083.                  A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
  4084.     D_Key[2] := SwapBits(B0, 0);
  4085.     D_Key[1] := SwapBits(B1, 0);
  4086.     D_Key[0] := SwapBits(B2, 0);
  4087.   end;
  4088. end;
  4089.  
  4090. procedure TCipher_3Way.DoEncode(Source, Dest: Pointer; Size: Integer);
  4091. var
  4092.   I: Integer;
  4093.   A0,A1,A2: LongWord;
  4094.   B0,B1,B2: LongWord;
  4095.   K0,K1,K2: LongWord;
  4096.   E: PLongWord;
  4097. begin
  4098.   Assert(Size = Context.BufferSize);
  4099.  
  4100.   with P3Way_Key(FUser)^ do
  4101.   begin
  4102.     K0 := E_Key[0];
  4103.     K1 := E_Key[1];
  4104.     K2 := E_Key[2];
  4105.     E  := @E_Data;
  4106.   end;
  4107.   A0 := PLongArray(Source)[0];
  4108.   A1 := PLongArray(Source)[1];
  4109.   A2 := PLongArray(Source)[2];
  4110.   for I := 0 to 10 do
  4111.   begin
  4112.     A0 := A0 xor K0 xor E^ shl 16;
  4113.     A1 := A1 xor K1;
  4114.     A2 := A2 xor K2 xor E^;
  4115.     Inc(E);
  4116.  
  4117.     B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
  4118.                  A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
  4119.                  A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
  4120.     B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
  4121.                  A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
  4122.                  A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
  4123.     B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
  4124.                  A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
  4125.                  A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
  4126.     B0 := B0 shr 10 or B0 shl 22;
  4127.     B2 := B2 shl  1 or B2 shr 31;
  4128.     A0 := B0 xor (B1 or not B2);
  4129.     A1 := B1 xor (B2 or not B0);
  4130.     A2 := B2 xor (B0 or not B1);
  4131.     A0 := A0 shl  1 or A0 shr 31;
  4132.     A2 := A2 shr 10 or A2 shl 22;
  4133.   end;
  4134.   A0 := A0 xor K0 xor E^ shl 16;
  4135.   A1 := A1 xor K1;
  4136.   A2 := A2 xor K2 xor E^;
  4137.   PLongArray(Dest)[0] := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
  4138.                                 A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
  4139.                                 A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
  4140.   PLongArray(Dest)[1] := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
  4141.                                 A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
  4142.                                 A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
  4143.   PLongArray(Dest)[2] := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
  4144.                                 A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
  4145.                                 A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
  4146. end;
  4147.  
  4148. procedure TCipher_3Way.DoDecode(Source, Dest: Pointer; Size: Integer);
  4149. var
  4150.   I: Integer;
  4151.   A0,A1,A2: LongWord;
  4152.   B0,B1,B2: LongWord;
  4153.   K0,K1,K2: LongWord;
  4154.   E: PLongWord;
  4155. begin
  4156.   Assert(Size = Context.BufferSize);
  4157.  
  4158.   with P3Way_Key(FUser)^ do
  4159.   begin
  4160.     K0 := D_Key[0];
  4161.     K1 := D_Key[1];
  4162.     K2 := D_Key[2];
  4163.     E  := @D_Data;
  4164.   end;
  4165.   A0 := SwapBits(PLongArray(Source)[2], 0);
  4166.   A1 := SwapBits(PLongArray(Source)[1], 0);
  4167.   A2 := SwapBits(PLongArray(Source)[0], 0);
  4168.   for I := 0 to 10 do
  4169.   begin
  4170.     A0 := A0 xor K0 xor E^ shl 16;
  4171.     A1 := A1 xor K1;
  4172.     A2 := A2 xor K2 xor E^;
  4173.     Inc(E);
  4174.  
  4175.     B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
  4176.                  A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
  4177.                  A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
  4178.     B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
  4179.                  A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
  4180.                  A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
  4181.     B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
  4182.                  A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
  4183.                  A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
  4184.     B0 := B0 shr 10 or B0 shl 22;
  4185.     B2 := B2 shl  1 or B2 shr 31;
  4186.     A0 := B0 xor (B1 or not B2);
  4187.     A1 := B1 xor (B2 or not B0);
  4188.     A2 := B2 xor (B0 or not B1);
  4189.     A0 := A0 shl  1 or A0 shr 31;
  4190.     A2 := A2 shr 10 or A2 shl 22;
  4191.   end;
  4192.   A0 := A0 xor K0 xor E^ shl 16;
  4193.   A1 := A1 xor K1;
  4194.   A2 := A2 xor K2 xor E^;
  4195.   B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
  4196.                A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
  4197.                A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
  4198.   B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
  4199.                A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
  4200.                A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
  4201.   B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
  4202.                A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
  4203.                A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
  4204.  
  4205.   PLongArray(Dest)[2] := SwapBits(B0, 0);
  4206.   PLongArray(Dest)[1] := SwapBits(B1, 0);
  4207.   PLongArray(Dest)[0] := SwapBits(B2, 0);
  4208. end;
  4209.  
  4210.  
  4211. // .TCipher_Cast128
  4212. class function TCipher_Cast128.Context: TCipherContext;
  4213. begin
  4214.   Result.KeySize := 16;
  4215.   Result.BlockSize := 8;
  4216.   Result.BufferSize := 8;
  4217.   Result.UserSize := 128;
  4218.   Result.UserSave := False;
  4219. end;
  4220.  
  4221. procedure TCipher_Cast128.SetRounds(Value: Integer);
  4222. begin
  4223.   if Value <> FRounds then
  4224.   begin
  4225.     if not (FState in [csNew, csInitialized, csDone]) then Done;
  4226.     if (FState <> csNew) and (Value <= 0) then Value := 16;
  4227.     FRounds := Value;
  4228.   end;
  4229. end;
  4230.  
  4231. procedure TCipher_Cast128.DoInit(const Key; Size: Integer);
  4232. var
  4233.   Z,X,T: array[0..3] of LongWord;
  4234.   K: PLongArray;
  4235.   I: LongWord;
  4236. begin
  4237.   if FRounds <= 0 then
  4238.     if Size <= 10 then FRounds := 12
  4239.       else FRounds := 16;
  4240.   K := FUser;
  4241.   FillChar(X, SizeOf(X), 0);
  4242.   Move(Key, X, Size);
  4243.   SwapLongBuffer(X, X, 4);
  4244.   I := 0;
  4245.   while I < 32 do
  4246.   begin
  4247.     if I and 4 = 0 then
  4248.     begin
  4249.       Z[0] := X[0] xor Cast128_Key[0, X[3] shr 16 and $FF] xor
  4250.                        Cast128_Key[1, X[3] and $FF] xor
  4251.                        Cast128_Key[2, X[3] shr 24] xor
  4252.                        Cast128_Key[3, X[3] shr  8 and $FF] xor
  4253.                        Cast128_Key[2, X[2] shr 24];
  4254.       T[0] := Z[0];
  4255.       Z[1] := X[2] xor Cast128_Key[0, Z[0] shr 24] xor
  4256.                        Cast128_Key[1, Z[0] shr  8 and $FF] xor
  4257.                        Cast128_Key[2, Z[0] shr 16 and $FF] xor
  4258.                        Cast128_Key[3, Z[0] and $FF] xor
  4259.                        Cast128_Key[3, X[2] shr  8 and $FF];
  4260.       T[1] := Z[1];
  4261.       Z[2] := X[3] xor Cast128_Key[0, Z[1] and $FF] xor
  4262.                        Cast128_Key[1, Z[1] shr  8 and $FF] xor
  4263.                        Cast128_Key[2, Z[1] shr 16 and $FF] xor
  4264.                        Cast128_Key[3, Z[1] shr 24] xor
  4265.                        Cast128_Key[0, X[2] shr 16 and $FF];
  4266.       T[2] := Z[2];
  4267.       Z[3] := X[1] xor Cast128_Key[0, Z[2] shr  8 and $FF] xor
  4268.                        Cast128_Key[1, Z[2] shr 16 and $FF] xor
  4269.                        Cast128_Key[2, Z[2] and $FF] xor
  4270.                        Cast128_Key[3, Z[2] shr 24] xor
  4271.                        Cast128_Key[1, X[2] and $FF];
  4272.       T[3] := Z[3];
  4273.     end else
  4274.     begin
  4275.       X[0] := Z[2] xor Cast128_Key[0, Z[1] shr 16 and $FF] xor
  4276.                        Cast128_Key[1, Z[1] and $FF] xor
  4277.                        Cast128_Key[2, Z[1] shr 24] xor
  4278.                        Cast128_Key[3, Z[1] shr  8 and $FF] xor
  4279.                        Cast128_Key[2, Z[0] shr 24];
  4280.       T[0] := X[0];
  4281.       X[1] := Z[0] xor Cast128_Key[0, X[0] shr 24] xor
  4282.                        Cast128_Key[1, X[0] shr  8 and $FF] xor
  4283.                        Cast128_Key[2, X[0] shr 16 and $FF] xor
  4284.                        Cast128_Key[3, X[0] and $FF] xor
  4285.                        Cast128_Key[3, Z[0] shr  8 and $FF];
  4286.       T[1] := X[1];
  4287.       X[2] := Z[1] xor Cast128_Key[0, X[1] and $FF] xor
  4288.                        Cast128_Key[1, X[1] shr  8 and $FF] xor
  4289.                        Cast128_Key[2, X[1] shr 16 and $FF] xor
  4290.                        Cast128_Key[3, X[1] shr 24] xor
  4291.                        Cast128_Key[0, Z[0] shr 16 and $FF];
  4292.       T[2] := X[2];
  4293.       X[3] := Z[3] xor Cast128_Key[0, X[2] shr  8 and $FF] xor
  4294.                        Cast128_Key[1, X[2] shr 16 and $FF] xor
  4295.                        Cast128_Key[2, X[2] and $FF] xor
  4296.                        Cast128_Key[3, X[2] shr 24] xor
  4297.                        Cast128_Key[1, Z[0] and $FF];
  4298.       T[3] := X[3];
  4299.     end;
  4300.     case I and 12 of
  4301.       0,12:
  4302.         begin
  4303.           K[I +0] := Cast128_Key[0, T[2] shr 24] xor
  4304.                      Cast128_Key[1, T[2] shr 16 and $FF] xor
  4305.                      Cast128_Key[2, T[1] and $FF] xor
  4306.                      Cast128_Key[3, T[1] shr  8 and $FF];
  4307.           K[I +1] := Cast128_Key[0, T[2] shr  8 and $FF] xor
  4308.                      Cast128_Key[1, T[2] and $FF] xor
  4309.                      Cast128_Key[2, T[1] shr 16 and $FF] xor
  4310.                      Cast128_Key[3, T[1] shr 24];
  4311.           K[I +2] := Cast128_Key[0, T[3] shr 24] xor
  4312.                      Cast128_Key[1, T[3] shr 16 and $FF] xor
  4313.                      Cast128_Key[2, T[0] and $FF] xor
  4314.                      Cast128_Key[3, T[0] shr  8 and $FF];
  4315.           K[I +3] := Cast128_Key[0, T[3] shr  8 and $FF] xor
  4316.                      Cast128_Key[1, T[3] and $FF] xor
  4317.                      Cast128_Key[2, T[0] shr 16 and $FF] xor
  4318.                      Cast128_Key[3, T[0] shr 24];
  4319.         end;
  4320.       4,8:
  4321.         begin
  4322.           K[I +0] := Cast128_Key[0, T[0] and $FF] xor
  4323.                      Cast128_Key[1, T[0] shr  8 and $FF] xor
  4324.                      Cast128_Key[2, T[3] shr 24] xor
  4325.                      Cast128_Key[3, T[3] shr 16 and $FF];
  4326.           K[I +1] := Cast128_Key[0, T[0] shr 16 and $FF] xor
  4327.                      Cast128_Key[1, T[0] shr 24] xor
  4328.                      Cast128_Key[2, T[3] shr  8 and $FF] xor
  4329.                      Cast128_Key[3, T[3] and $FF];
  4330.           K[I +2] := Cast128_Key[0, T[1] and $FF] xor
  4331.                      Cast128_Key[1, T[1] shr  8 and $FF] xor
  4332.                      Cast128_Key[2, T[2] shr 24] xor
  4333.                      Cast128_Key[3, T[2] shr 16 and $FF];
  4334.           K[I +3] := Cast128_Key[0, T[1] shr 16 and $FF] xor
  4335.                      Cast128_Key[1, T[1] shr 24] xor
  4336.                      Cast128_Key[2, T[2] shr  8 and $FF] xor
  4337.                      Cast128_Key[3, T[2] and $FF];
  4338.         end;
  4339.     end;
  4340.     case I and 12 of
  4341.       0: begin
  4342.            K[I +0] := K[I +0] xor Cast128_Key[0, Z[0] shr  8 and $FF];
  4343.            K[I +1] := K[I +1] xor Cast128_Key[1, Z[1] shr  8 and $FF];
  4344.            K[I +2] := K[I +2] xor Cast128_Key[2, Z[2] shr 16 and $FF];
  4345.            K[I +3] := K[I +3] xor Cast128_Key[3, Z[3] shr 24];
  4346.          end;
  4347.       4: begin
  4348.            K[I +0] := K[I +0] xor Cast128_Key[0, X[2] shr 24];
  4349.            K[I +1] := K[I +1] xor Cast128_Key[1, X[3] shr 16 and $FF];
  4350.            K[I +2] := K[I +2] xor Cast128_Key[2, X[0] and $FF];
  4351.            K[I +3] := K[I +3] xor Cast128_Key[3, X[1] and $FF];
  4352.          end;
  4353.       8: begin
  4354.            K[I +0] := K[I +0] xor Cast128_Key[0, Z[2] shr 16 and $FF];
  4355.            K[I +1] := K[I +1] xor Cast128_Key[1, Z[3] shr 24];
  4356.            K[I +2] := K[I +2] xor Cast128_Key[2, Z[0] shr  8 and $FF];
  4357.            K[I +3] := K[I +3] xor Cast128_Key[3, Z[1] shr  8 and $FF];
  4358.          end;
  4359.      12: begin
  4360.           K[I +0] := K[I +0] xor Cast128_Key[0, X[0] and $FF];
  4361.           K[I +1] := K[I +1] xor Cast128_Key[1, X[1] and $FF];
  4362.           K[I +2] := K[I +2] xor Cast128_Key[2, X[2] shr 24];
  4363.           K[I +3] := K[I +3] xor Cast128_Key[3, X[3] shr 16 and $FF];
  4364.         end;
  4365.     end;
  4366.     if I >= 16 then
  4367.     begin
  4368.       K[I +0] := K[I +0] and $1F;
  4369.       K[I +1] := K[I +1] and $1F;
  4370.       K[I +2] := K[I +2] and $1F;
  4371.       K[I +3] := K[I +3] and $1F;
  4372.     end;
  4373.     Inc(I, 4);
  4374.   end;
  4375.   ProtectBuffer(X, SizeOf(X));
  4376.   ProtectBuffer(Z, SizeOf(Z));
  4377.   ProtectBuffer(T, SizeOf(T));
  4378. end;
  4379.  
  4380. procedure TCipher_Cast128.DoEncode(Source, Dest: Pointer; Size: Integer);
  4381. var
  4382.   T,I,A,B: LongWord;
  4383.   K: PLongArray;
  4384. begin
  4385.   Assert(Size = Context.BufferSize);
  4386.  
  4387.   K := FUser;
  4388.   A := SwapLong(PLongArray(Source)[0]);
  4389.   B := SwapLong(PLongArray(Source)[1]);
  4390.   for I := 0 to 2 do
  4391.   begin
  4392.     T := K[0] + B;
  4393.     T := T shl K[16] or T shr (32 - K[16]);
  4394.     A := A xor (Cast128_Data[0, T shr 24] xor
  4395.                 Cast128_Data[1, T shr 16 and $FF] -
  4396.                 Cast128_Data[2, T shr  8 and $FF] +
  4397.                 Cast128_Data[3, T and $FF]);
  4398.     T := K[1] xor A;
  4399.     T := T shl K[17] or T shr (32 - K[17]);
  4400.     B := B xor (Cast128_Data[0, T shr 24] -
  4401.                 Cast128_Data[1, T shr 16 and $FF] +
  4402.                 Cast128_Data[2, T shr  8 and $FF] xor
  4403.                 Cast128_Data[3, T and $FF]);
  4404.     T := K[2] - B;
  4405.     T := T shl K[18] or T shr (32 - K[18]);
  4406.     A := A xor (Cast128_Data[0, T shr 24] +
  4407.                 Cast128_Data[1, T shr 16 and $FF] xor
  4408.                 Cast128_Data[2, T shr  8 and $FF] -
  4409.                 Cast128_Data[3, T and $FF]);
  4410.     T := K[3] + A;
  4411.     T := T shl K[19] or T shr (32 - K[19]);
  4412.     B := B xor (Cast128_Data[0, T shr 24] xor
  4413.                 Cast128_Data[1, T shr 16 and $FF] -
  4414.                 Cast128_Data[2, T shr  8 and $FF] +
  4415.                 Cast128_Data[3, T and $FF]);
  4416.     if I = 2 then Break;
  4417.     T := K[4] xor B;
  4418.     T := T shl K[20] or T shr (32 - K[20]);
  4419.     A := A xor (Cast128_Data[0, T shr 24] -
  4420.                 Cast128_Data[1, T shr 16 and $FF] +
  4421.                 Cast128_Data[2, T shr  8 and $FF] xor
  4422.                 Cast128_Data[3, T and $FF]);
  4423.     T := K[5] - A;
  4424.     T := T shl K[21] or T shr (32 - K[21]);
  4425.     B := B xor (Cast128_Data[0, T shr 24] +
  4426.                 Cast128_Data[1, T shr 16 and $FF] xor
  4427.                 Cast128_Data[2, T shr  8 and $FF] -
  4428.                 Cast128_Data[3, T and $FF]);
  4429.     if (I = 1) and (FRounds <= 12) then Break;
  4430.     K := @K[6];
  4431.   end;
  4432.   PLongArray(Dest)[0] := SwapLong(B);
  4433.   PLongArray(Dest)[1] := SwapLong(A);
  4434. end;
  4435.  
  4436. procedure TCipher_Cast128.DoDecode(Source, Dest: Pointer; Size: Integer);
  4437. var
  4438.   T,I,A,B: LongWord;
  4439.   K: PLongArray;
  4440. label
  4441.   Start;
  4442. begin
  4443.   Assert(Size = Context.BufferSize);
  4444.  
  4445.   K := @PLongArray(FUser)[12];
  4446.   B := SwapLong(PLongArray(Source)[0]);
  4447.   A := SwapLong(PLongArray(Source)[1]);
  4448.   I := 2;
  4449.   if FRounds <= 12 then Dec(PLongWord(K), 6)
  4450.     else goto Start;
  4451.   while I > 0 do
  4452.   begin
  4453.     Dec(I);
  4454.     T := K[5] - A;
  4455.     T := T shl K[21] or T shr (32 - K[21]);
  4456.     B := B xor (Cast128_Data[0, T shr 24] +
  4457.                 Cast128_Data[1, T shr 16 and $FF] xor
  4458.                 Cast128_Data[2, T shr  8 and $FF] -
  4459.                 Cast128_Data[3, T and $FF]);
  4460.     T := K[4] xor B;
  4461.     T := T shl K[20] or T shr (32 - K[20]);
  4462.     A := A xor (Cast128_Data[0, T shr 24] -
  4463.                 Cast128_Data[1, T shr 16 and $FF] +
  4464.                 Cast128_Data[2, T shr  8 and $FF] xor
  4465.                 Cast128_Data[3, T and $FF]);
  4466. Start:
  4467.     T := K[3] + A;
  4468.     T := T shl K[19] or T shr (32 - K[19]);
  4469.     B := B xor (Cast128_Data[0, T shr 24] xor
  4470.                 Cast128_Data[1, T shr 16 and $FF] -
  4471.                 Cast128_Data[2, T shr  8 and $FF] +
  4472.                 Cast128_Data[3, T and $FF]);
  4473.     T := K[2] - B;
  4474.     T := T shl K[18] or T shr (32 - K[18]);
  4475.     A := A xor (Cast128_Data[0, T shr 24] +
  4476.                 Cast128_Data[1, T shr 16 and $FF] xor
  4477.                 Cast128_Data[2, T shr  8 and $FF] -
  4478.                 Cast128_Data[3, T and $FF]);
  4479.     T := K[1] xor A;
  4480.     T := T shl K[17] or T shr (32 - K[17]);
  4481.     B := B xor (Cast128_Data[0, T shr 24] -
  4482.                 Cast128_Data[1, T shr 16 and $FF] +
  4483.                 Cast128_Data[2, T shr  8 and $FF] xor
  4484.                 Cast128_Data[3, T and $FF]);
  4485.     T := K[0] + B;
  4486.     T := T shl K[16] or T shr (32 - K[16]);
  4487.     A := A xor (Cast128_Data[0, T shr 24] xor
  4488.                 Cast128_Data[1, T shr 16 and $FF] -
  4489.                 Cast128_Data[2, T shr  8 and $FF] +
  4490.                 Cast128_Data[3, T and $FF]);
  4491.     Dec(PLongWord(K), 6);
  4492.   end;
  4493.   PLongArray(Dest)[0] := SwapLong(A);
  4494.   PLongArray(Dest)[1] := SwapLong(B);
  4495. end;
  4496.  
  4497. // .TCipher_Gost
  4498. class function TCipher_Gost.Context: TCipherContext;
  4499. begin
  4500.   Result.KeySize := 32;
  4501.   Result.BlockSize := 8;
  4502.   Result.BufferSize := 8;
  4503.   Result.UserSize := 32;
  4504.   Result.UserSave := False;
  4505. end;
  4506.  
  4507. procedure TCipher_Gost.DoInit(const Key; Size: Integer);
  4508. begin
  4509.   Move(Key, FUser^, Size);
  4510. end;
  4511.  
  4512. procedure TCipher_Gost.DoEncode(Source, Dest: Pointer; Size: Integer);
  4513. var
  4514.   I,A,B,T: LongWord;
  4515.   K: PLongArray;
  4516. begin
  4517.   Assert(Size = Context.BufferSize);
  4518.  
  4519.   K := FUser;
  4520.   A := PLongArray(Source)[0];
  4521.   B := PLongArray(Source)[1];
  4522.   for I := 0 to 11 do
  4523.   begin
  4524.     if I and 3 = 0 then K := FUser;
  4525.     T := A + K[0];
  4526.     B := B xor Gost_Data[0, T        and $FF] xor
  4527.                Gost_Data[1, T shr  8 and $FF] xor
  4528.                Gost_Data[2, T shr 16 and $FF] xor
  4529.                Gost_Data[3, T shr 24        ];
  4530.     T := B + K[1];
  4531.     A := A xor Gost_Data[0, T        and $FF] xor
  4532.                Gost_Data[1, T shr  8 and $FF] xor
  4533.                Gost_Data[2, T shr 16 and $FF] xor
  4534.                Gost_Data[3, T shr 24        ];
  4535.     K := @K[2];
  4536.   end;
  4537.   K := @PLongArray(FUser)[6];
  4538.   for I := 0 to 3 do
  4539.   begin
  4540.     T := A + K[1];
  4541.     B := B xor Gost_Data[0, T        and $FF] xor
  4542.                Gost_Data[1, T shr  8 and $FF] xor
  4543.                Gost_Data[2, T shr 16 and $FF] xor
  4544.                Gost_Data[3, T shr 24        ];
  4545.     T := B + K[0];
  4546.     A := A xor Gost_Data[0, T        and $FF] xor
  4547.                Gost_Data[1, T shr  8 and $FF] xor
  4548.                Gost_Data[2, T shr 16 and $FF] xor
  4549.                Gost_Data[3, T shr 24        ];
  4550.     Dec(PLongWord(K), 2);
  4551.   end;
  4552.   PLongArray(Dest)[0] := B;
  4553.   PLongArray(Dest)[1] := A;
  4554. end;
  4555.  
  4556. procedure TCipher_Gost.DoDecode(Source, Dest: Pointer; Size: Integer);
  4557. var
  4558.   I,A,B,T: LongWord;
  4559.   K: PLongArray;
  4560. begin
  4561.   Assert(Size = Context.BufferSize);
  4562.  
  4563.   A := PLongArray(Source)[0];
  4564.   B := PLongArray(Source)[1];
  4565.   K := FUser;
  4566.   for I := 0 to 3 do
  4567.   begin
  4568.     T := A + K[0];
  4569.     B := B xor Gost_Data[0, T and $FF] xor
  4570.                Gost_Data[1, T shr  8 and $FF] xor
  4571.                Gost_Data[2, T shr 16 and $FF] xor
  4572.                Gost_Data[3, T shr 24];
  4573.     T := B + K[1];
  4574.     A := A xor Gost_Data[0, T and $FF] xor
  4575.                Gost_Data[1, T shr  8 and $FF] xor
  4576.                Gost_Data[2, T shr 16 and $FF] xor
  4577.                Gost_Data[3, T shr 24];
  4578.     K := @K[2];
  4579.   end;
  4580.   for I := 0 to 11 do
  4581.   begin
  4582.     if I and 3 = 0 then K := @PLongArray(FUser)[6];
  4583.     T := A + K[1];
  4584.     B := B xor Gost_Data[0, T and $FF] xor
  4585.                Gost_Data[1, T shr  8 and $FF] xor
  4586.                Gost_Data[2, T shr 16 and $FF] xor
  4587.                Gost_Data[3, T shr 24];
  4588.     T := B + K[0];
  4589.     A := A xor Gost_Data[0, T and $FF] xor
  4590.                Gost_Data[1, T shr  8 and $FF] xor
  4591.                Gost_Data[2, T shr 16 and $FF] xor
  4592.                Gost_Data[3, T shr 24];
  4593.     Dec(PLongWord(K), 2);
  4594.   end;
  4595.   PLongArray(Dest)[0] := B;
  4596.   PLongArray(Dest)[1] := A;
  4597. end;
  4598.  
  4599. // .TCipher_Misty
  4600. class function TCipher_Misty.Context: TCipherContext;
  4601. begin
  4602.   Result.KeySize := 16;
  4603.   Result.BlockSize := 8;
  4604.   Result.BufferSize := 8;
  4605.   Result.UserSize := 128;
  4606.   Result.UserSave := False;
  4607. end;
  4608.  
  4609. function Misty_I(Value, Key: LongWord): LongWord;
  4610. begin
  4611.   Result := Misty_Data9[Value shr 7 and $1FF] xor (Value and $7F);
  4612.   Value := (Misty_Data7[Value and $7F] xor Result and $7F) xor (Key shr 9 and $7F);
  4613.   Result := Misty_Data9[Result xor (Key and $1FF)] xor Value or Value shl 9;
  4614. end;
  4615.  
  4616. function Misty_O(Value, K: LongWord; Key: PLongArray): LongWord;
  4617. begin
  4618.   Result := Misty_I((Value shr 16) xor Key[K], Key[(K + 5) and 7 + 8]) xor (Value and $FFFF);
  4619.   Value  := Misty_I((Value and $FFFF) xor Key[(K + 2) and 7], Key[(K + 1) and 7 + 8]) xor Result;
  4620.   Result := Misty_I(Result xor Key[(K + 7) and 7], Key[(K + 3) and 7 + 8]) xor Value;
  4621.   Result := Result or (Value xor Key[(k+4) and 7]) shl 16;
  4622. end;
  4623.  
  4624. function Misty_E(Value, K: LongWord; Key: PLongArray): LongWord;
  4625. begin
  4626.   Result := Value shr 16;
  4627.   Value  := Value and $FFFF;
  4628.   if K and 1 <> 0 then
  4629.   begin
  4630.     K      := K shr 1;
  4631.     Value  := Value  xor (Result and Key[(K + 2) and 7 + 8]);
  4632.     Result := Result xor (Value  or  Key[(K + 4) and 7]);
  4633.   end else
  4634.   begin
  4635.     K      := K shr 1;
  4636.     Value  := Value  xor (Result and Key[K]);
  4637.     Result := Result xor (Value  or  Key[(K + 6) and 7 + 8]);
  4638.   end;
  4639.   Result:= (Result shl 16) or Value;
  4640. end;
  4641.  
  4642. function Misty_D(Value, K: LongWord; Key: PLongArray): LongWord;
  4643. begin
  4644.   Result := Value shr 16;
  4645.   Value  := Value and $FFFF;
  4646.   if K and 1 <> 0 then
  4647.   begin
  4648.     K      := K shr 1;
  4649.     Result := Result xor (Value  or  Key[(K + 4) and 7]);
  4650.     Value  := Value  xor (Result and Key[(K + 2) and 7 + 8]);
  4651.   end else
  4652.   begin
  4653.     K      := K shr 1;
  4654.     Result := Result xor (Value  or  Key[(K +6) and 7 + 8]);
  4655.     Value  := Value  xor (Result and Key[K]);
  4656.   end;
  4657.   Result:= (Result shl 16) or Value;
  4658. end;
  4659.  
  4660. procedure TCipher_Misty.DoInit(const Key; Size: Integer);
  4661. var
  4662.   K: array[0..15] of Byte;
  4663.   D: PLongArray;
  4664.   I: Integer;
  4665. begin
  4666.   FillChar(K, SizeOf(K), 0);
  4667.   Move(Key, K, Size);
  4668.   D := FUser;
  4669.   for I := 0 to 7 do
  4670.     D[I] := K[I * 2] * 256 + K[I * 2 +1];
  4671.   for I := 0 to 7 do
  4672.   begin
  4673.     D[I +  8] := Misty_I(D[I], D[(I + 1) and 7]);
  4674.     D[I + 16] := D[I + 8] and $1FF;
  4675.     D[I + 24] := D[I + 8] shr 9;
  4676.   end;
  4677.   ProtectBuffer(K, SizeOf(K));
  4678. end;
  4679.  
  4680. procedure TCipher_Misty.DoEncode(Source, Dest: Pointer; Size: Integer);
  4681. var
  4682.   A,B: LongWord;
  4683. begin
  4684.   Assert(Size = Context.BufferSize);
  4685.  
  4686.   A := PLongArray(Source)[0];
  4687.   B := PLongArray(Source)[1];
  4688.   A := Misty_E(A, 0, FUser);
  4689.   B := Misty_E(B, 1, FUser) xor Misty_O(A, 0, FUser);
  4690.   A := A xor Misty_O(B, 1, FUser);
  4691.   A := Misty_E(A, 2, FUser);
  4692.   B := Misty_E(B, 3, FUser) xor Misty_O(A, 2, FUser);
  4693.   A := A xor Misty_O(B, 3, FUser);
  4694.   A := Misty_E(A, 4, FUser);
  4695.   B := Misty_E(B, 5, FUser) xor Misty_O(A, 4, FUser);
  4696.   A := A xor Misty_O(B, 5, FUser);
  4697.   A := Misty_E(A, 6, FUser);
  4698.   B := Misty_E(B, 7, FUser) xor Misty_O(A, 6, FUser);
  4699.   A := A xor Misty_O(B, 7, FUser);
  4700.   PLongArray(Dest)[0] := Misty_E(B, 9, FUser);
  4701.   PLongArray(Dest)[1] := Misty_E(A, 8, FUser);
  4702. end;
  4703.  
  4704. procedure TCipher_Misty.DoDecode(Source, Dest: Pointer; Size: Integer);
  4705. var
  4706.   A,B: LongWord;
  4707. begin
  4708.   Assert(Size = Context.BufferSize);
  4709.  
  4710.   B := Misty_D(PLongArray(Source)[0], 9, FUser);
  4711.   A := Misty_D(PLongArray(Source)[1], 8, FUser);
  4712.   A := A xor Misty_O(B, 7, FUser);
  4713.   B := Misty_D(B xor Misty_O(A, 6, FUser), 7, FUser);
  4714.   A := Misty_D(A, 6, FUser);
  4715.   A := A xor Misty_O(B, 5, FUser);
  4716.   B := Misty_D(B xor Misty_O(A, 4, FUser), 5, FUser);
  4717.   A := Misty_D(A, 4, FUser);
  4718.   A := A xor Misty_O(B, 3, FUser);
  4719.   B := Misty_D(B xor Misty_O(A, 2, FUser), 3, FUser);
  4720.   A := Misty_D(A, 2, FUser);
  4721.   A := A xor Misty_O(B, 1, FUser);
  4722.   PLongArray(Dest)[0] := Misty_D(A, 0, FUser);
  4723.   PLongArray(Dest)[1] := Misty_D(B xor Misty_O(A, 0, FUser), 1, FUser);
  4724. end;
  4725.  
  4726. // .TCipher_NewDES
  4727. class function TCipher_NewDES.Context: TCipherContext;
  4728. begin
  4729.   Result.KeySize := 15;
  4730.   Result.BlockSize := 8;
  4731.   Result.BufferSize := 8;
  4732.   Result.UserSize := 60 * 2;
  4733.   Result.UserSave := True;
  4734. end;
  4735.  
  4736. procedure TCipher_NewDES.DoInit(const Key; Size: Integer);
  4737. var
  4738.   K: array[0..14] of Byte;
  4739.   E: PByteArray;
  4740.   I: Integer;
  4741. begin
  4742.   FillChar(K, SizeOf(K), 0);
  4743.   Move(Key, K, Size);
  4744.   E := FUser;
  4745.   Move(K, E[ 0], 15);
  4746.   Move(K, E[15], 15);
  4747.   Move(K, E[30], 15);
  4748.   Move(K, E[45], 15);
  4749.   E := @E[60];
  4750.   I := 11;
  4751.   repeat
  4752.     E[0] := K[I]; I := (I +1) mod 15;
  4753.     E[1] := K[I]; I := (I +1) mod 15;
  4754.     E[2] := K[I]; I := (I +1) mod 15;
  4755.     E[3] := K[I]; I := (I +9) mod 15;
  4756.     if I = 12 then Break;
  4757.     E[4] := K[I]; Inc(I);
  4758.     E[5] := K[I]; Inc(I);
  4759.     E[6] := K[I]; I := (I + 9) mod 15;
  4760.     E := @E[7];
  4761.   until False;
  4762.   ProtectBuffer(K, SizeOf(K));
  4763. end;
  4764.  
  4765. procedure NewDES_Func(Source, Dest, Key: PByteArray);
  4766. var
  4767.   I: Integer;
  4768.   A,B,C,D,E,F,G,H: Byte;
  4769. begin
  4770.   A := Source[0];
  4771.   B := Source[1];
  4772.   C := Source[2];
  4773.   D := Source[3];
  4774.   E := Source[4];
  4775.   F := Source[5];
  4776.   G := Source[6];
  4777.   H := Source[7];
  4778.   for I := 0 to 7 do
  4779.   begin
  4780.     E := E xor NewDES_Data[A xor Key[0]];
  4781.     F := F xor NewDES_Data[B xor Key[1]];
  4782.     G := G xor NewDES_Data[C xor Key[2]];
  4783.     H := H xor NewDES_Data[D xor Key[3]];
  4784.     B := B xor NewDES_Data[E xor Key[4]];
  4785.     C := C xor NewDES_Data[F xor E];
  4786.     D := D xor NewDES_Data[G xor Key[5]];
  4787.     A := A xor NewDES_Data[H xor Key[6]];
  4788.     Key := @Key[7];
  4789.   end;
  4790.   E := E xor NewDES_Data[A xor Key[0]];
  4791.   F := F xor NewDES_Data[B xor Key[1]];
  4792.   G := G xor NewDES_Data[C xor Key[2]];
  4793.   H := H xor NewDES_Data[D xor Key[3]];
  4794.   Dest[0] := A;
  4795.   Dest[1] := B;
  4796.   Dest[2] := C;
  4797.   Dest[3] := D;
  4798.   Dest[4] := E;
  4799.   Dest[5] := F;
  4800.   Dest[6] := G;
  4801.   Dest[7] := H;
  4802. end;
  4803.  
  4804. procedure TCipher_NewDES.DoEncode(Source, Dest: Pointer; Size: Integer);
  4805. begin
  4806.   Assert(Size = Context.BufferSize);
  4807.   NewDES_Func(Source, Dest, FUser);
  4808. end;
  4809.  
  4810. procedure TCipher_NewDES.DoDecode(Source, Dest: Pointer; Size: Integer);
  4811. begin
  4812.   Assert(Size = Context.BufferSize);
  4813.   NewDES_Func(Source, Dest, @PByteArray(FUser)[60]);
  4814. end;
  4815.  
  4816. // .TCipher_Q128
  4817. class function TCipher_Q128.Context: TCipherContext;
  4818. begin
  4819.   Result.KeySize := 16;
  4820.   Result.BlockSize := 16;
  4821.   Result.BufferSize := 16;
  4822.   Result.UserSize := 256;
  4823.   Result.UserSave := False;
  4824. end;
  4825.  
  4826. procedure TCipher_Q128.DoInit(const Key; Size: Integer);
  4827. var
  4828.   K: array[0..3] of LongWord;
  4829.   D: PLongArray;
  4830.   I: Integer;
  4831. begin
  4832.   FillChar(K, SizeOf(K), 0);
  4833.   Move(Key, K, Size);
  4834.   D := FUser;
  4835.   for I := 19 downto 1 do
  4836.   begin
  4837.     K[1] := K[1] xor Q128_Data[K[0] and $03FF]; K[0] := K[0] shr 10 or K[0] shl 22;
  4838.     K[2] := K[2] xor Q128_Data[K[1] and $03FF]; K[1] := K[1] shr 10 or K[1] shl 22;
  4839.     K[3] := K[3] xor Q128_Data[K[2] and $03FF]; K[2] := K[2] shr 10 or K[2] shl 22;
  4840.     K[0] := K[0] xor Q128_Data[K[3] and $03FF]; K[3] := K[3] shr 10 or K[3] shl 22;
  4841.     if I <= 16 then
  4842.     begin
  4843.       D[0] := K[0];
  4844.       D[1] := K[1];
  4845.       D[2] := K[2];
  4846.       D[3] := K[3];
  4847.       D := @D[4];
  4848.     end;
  4849.   end;
  4850.   ProtectBuffer(K, SizeOf(K));
  4851. end;
  4852.  
  4853. procedure TCipher_Q128.DoEncode(Source, Dest: Pointer; Size: Integer);
  4854. {$IFDEF UseASM}
  4855. asm
  4856.        PUSH   ESI
  4857.        PUSH   EDI
  4858.        PUSH   EBX
  4859.        PUSH   EBP
  4860.        PUSH   ECX
  4861.        MOV    EDI,[EAX].TCipher_Q128.FUser
  4862.        MOV    EAX,[EDX +  0]  // B0
  4863.        MOV    EBX,[EDX +  4]  // B1
  4864.        MOV    ECX,[EDX +  8]  // B2
  4865.        MOV    EDX,[EDX + 12]  // B3
  4866.        MOV    EBP,16
  4867. @@1:   MOV    ESI,EAX
  4868.        ROL    ESI,10
  4869.        AND    EAX,03FFh
  4870.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4871.        ADD    EAX,[EDI + 0]
  4872.        XOR    EAX,EBX
  4873.        MOV    EBX,EAX
  4874.        ROL    EBX,10
  4875.        AND    EAX,03FFh
  4876.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4877.        ADD    EAX,[EDI + 4]
  4878.        XOR    EAX,ECX
  4879.        MOV    ECX,EAX
  4880.        ROL    ECX,10
  4881.        AND    EAX,03FFh
  4882.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4883.        ADD    EAX,[EDI + 8]
  4884.        XOR    EAX,EDX
  4885.        MOV    EDX,EAX
  4886.        ROL    EDX,10
  4887.        AND    EAX,03FFh
  4888.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4889.        ADD    EAX,[EDI + 12]
  4890.        XOR    EAX,ESI
  4891.        DEC    EBP
  4892.        LEA    EDI,[EDI + 16]
  4893.        JNZ    @@1
  4894.        POP    ESI
  4895.        MOV    [ESI +  0],EAX  // B0
  4896.        MOV    [ESI +  4],EBX  // B1
  4897.        MOV    [ESI +  8],ECX  // B2
  4898.        MOV    [ESI + 12],EDX  // B3
  4899.        POP    EBP
  4900.        POP    EBX
  4901.        POP    EDI
  4902.        POP    ESI
  4903. end;
  4904. {$ELSE}
  4905. var
  4906.   D: PLongArray;
  4907.   B0,B1,B2,B3,I: LongWord;
  4908. begin
  4909.   Assert(Size = Context.BufferSize);
  4910.  
  4911.   D  := FUser;
  4912.   B0 := PLongArray(Source)[0];
  4913.   B1 := PLongArray(Source)[1];
  4914.   B2 := PLongArray(Source)[2];
  4915.   B3 := PLongArray(Source)[3];
  4916.   for I := 0 to 15 do
  4917.   begin
  4918.     B1 := B1 xor (Q128_Data[B0 and $03FF] + D[0]); B0 := B0 shl 10 or B0 shr 22;
  4919.     B2 := B2 xor (Q128_Data[B1 and $03FF] + D[1]); B1 := B1 shl 10 or B1 shr 22;
  4920.     B3 := B3 xor (Q128_Data[B2 and $03FF] + D[2]); B2 := B2 shl 10 or B2 shr 22;
  4921.     B0 := B0 xor (Q128_Data[B3 and $03FF] + D[3]); B3 := B3 shl 10 or B3 shr 22;
  4922.     D := @D[4];
  4923.   end;
  4924.   PLongArray(Dest)[0] := B0;
  4925.   PLongArray(Dest)[1] := B1;
  4926.   PLongArray(Dest)[2] := B2;
  4927.   PLongArray(Dest)[3] := B3;
  4928. end;
  4929. {$ENDIF}
  4930.  
  4931. procedure TCipher_Q128.DoDecode(Source, Dest: Pointer; Size: Integer);
  4932. {$IFDEF UseASM}
  4933. asm
  4934.        PUSH   ESI
  4935.        PUSH   EDI
  4936.        PUSH   EBX
  4937.        PUSH   EBP
  4938.        PUSH   ECX
  4939.        MOV    EDI,[EAX].TCipher_Q128.FUser
  4940.        LEA    EDI,[EDI + 64 * 4]
  4941.        MOV    ESI,[EDX +  0]   // B0
  4942.        MOV    EBX,[EDX +  4]  // B1
  4943.        MOV    ECX,[EDX +  8]  // B2
  4944.        MOV    EDX,[EDX + 12]  // B3
  4945.        MOV    EBP,16
  4946. @@1:   SUB    EDI,16
  4947.        ROR    EDX,10
  4948.        MOV    EAX,EDX
  4949.        AND    EAX,03FFh
  4950.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4951.        ADD    EAX,[EDI + 12]
  4952.        XOR    ESI,EAX
  4953.        ROR    ECX,10
  4954.        MOV    EAX,ECX
  4955.        AND    EAX,03FFh
  4956.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4957.        ADD    EAX,[EDI +  8]
  4958.        XOR    EDX,EAX
  4959.        ROR    EBX,10
  4960.        MOV    EAX,EBX
  4961.        AND    EAX,03FFh
  4962.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4963.        ADD    EAX,[EDI +  4]
  4964.        XOR    ECX,EAX
  4965.        ROR    ESI,10
  4966.        MOV    EAX,ESI
  4967.        AND    EAX,03FFh
  4968.        MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
  4969.        ADD    EAX,[EDI]
  4970.        XOR    EBX,EAX
  4971.        DEC    EBP
  4972.        JNZ    @@1
  4973.        POP    EAX
  4974.        MOV    [EAX +  0],ESI  // B0
  4975.        MOV    [EAX +  4],EBX  // B1
  4976.        MOV    [EAX +  8],ECX  // B2
  4977.        MOV    [EAX + 12],EDX  // B3
  4978.        POP    EBP
  4979.        POP    EBX
  4980.        POP    EDI
  4981.        POP    ESI
  4982. end;
  4983. {$ELSE}
  4984. var
  4985.   D: PLongArray;
  4986.   B0,B1,B2,B3,I: LongWord;
  4987. begin
  4988.   Assert(Size = Context.BufferSize);
  4989.  
  4990.   D  := @PLongArray(FUser)[60];
  4991.   B0 := PLongArray(Source)[0];
  4992.   B1 := PLongArray(Source)[1];
  4993.   B2 := PLongArray(Source)[2];
  4994.   B3 := PLongArray(Source)[3];
  4995.   for I := 0 to 15 do
  4996.   begin
  4997.     B3 := B3 shr 10 or B3 shl 22; B0 := B0 xor (Q128_Data[B3 and $03FF] + D[3]);
  4998.     B2 := B2 shr 10 or B2 shl 22; B3 := B3 xor (Q128_Data[B2 and $03FF] + D[2]);
  4999.     B1 := B1 shr 10 or B1 shl 22; B2 := B2 xor (Q128_Data[B1 and $03FF] + D[1]);
  5000.     B0 := B0 shr 10 or B0 shl 22; B1 := B1 xor (Q128_Data[B0 and $03FF] + D[0]);
  5001.     Dec(PLongWord(D), 4);
  5002.   end;
  5003.   PLongArray(Dest)[0] := B0;
  5004.   PLongArray(Dest)[1] := B1;
  5005.   PLongArray(Dest)[2] := B2;
  5006.   PLongArray(Dest)[3] := B3;
  5007. end;
  5008. {$ENDIF}
  5009.  
  5010. // .TCipher_RC2
  5011. class function TCipher_RC2.Context: TCipherContext;
  5012. begin
  5013.   Result.KeySize := 128;
  5014.   Result.BlockSize := 8;
  5015.   Result.BufferSize := 8;
  5016.   Result.UserSize := 128;
  5017.   Result.UserSave := False;
  5018. end;
  5019.  
  5020. procedure TCipher_RC2.DoInit(const Key; Size: Integer);
  5021. // New keysheduling according to RFC2268 and its testcases.
  5022. // the v3.0 keysetup was an older, bad version
  5023. // special thanks goes to Brendan Bosnan to pointing me out that.
  5024. var
  5025.   I,L,Mask,KeyEffectiveBits: Integer;
  5026.   K: PByteArray;
  5027. begin
  5028.   if Size <= 0 then Exit;
  5029.   KeyEffectiveBits := Size * 8;
  5030.   L := KeyEffectiveBits and 7;
  5031.   if L = 0 then Mask := $FF
  5032.     else Mask := $FF shr (8 - L);
  5033.   L := (KeyEffectiveBits + 7) shr 3;
  5034.   K := FUser;
  5035.   Move(Key, K[0], Size);
  5036.   for I := Size to 127 do
  5037.     K[I] := RC2_Data[(K[I - Size] + K[I - 1]) and $FF];
  5038.   K[128 - L] := RC2_Data[K[128 - L] and Mask];
  5039.   for I := 127 - L downto 0 do
  5040.      K[I] := RC2_Data[K[I + 1] xor K[I + L]];
  5041. end;
  5042.  
  5043. procedure TCipher_RC2.DoEncode(Source, Dest: Pointer; Size: Integer);
  5044. var
  5045.   I: Integer;
  5046.   K: PWordArray;
  5047.   A,B,C,D: Word;
  5048. begin
  5049.   Assert(Size = Context.BufferSize);
  5050.  
  5051.   K := FUser;
  5052.   A := PWordArray(Source)[0];
  5053.   B := PWordArray(Source)[1];
  5054.   C := PWordArray(Source)[2];
  5055.   D := PWordArray(Source)[3];
  5056.   for I := 0 to 15 do
  5057.   begin
  5058.     Inc(A, (B and not D) + (C and D) + K[I * 4 +0]); A := A shl 1 or A shr 15;
  5059.     Inc(B, (C and not A) + (D and A) + K[I * 4 +1]); B := B shl 2 or B shr 14;
  5060.     Inc(C, (D and not B) + (A and B) + K[I * 4 +2]); C := C shl 3 or C shr 13;
  5061.     Inc(D, (A and not C) + (B and C) + K[I * 4 +3]); D := D shl 5 or D shr 11;
  5062.     if I in [4, 10] then
  5063.     begin
  5064.       Inc(A, K[D and $3F]);
  5065.       Inc(B, K[A and $3F]);
  5066.       Inc(C, K[B and $3F]);
  5067.       Inc(D, K[C and $3F]);
  5068.     end;
  5069.   end;
  5070.   PWordArray(Dest)[0] := A;
  5071.   PWordArray(Dest)[1] := B;
  5072.   PWordArray(Dest)[2] := C;
  5073.   PWordArray(Dest)[3] := D;
  5074. end;
  5075.  
  5076. procedure TCipher_RC2.DoDecode(Source, Dest: Pointer; Size: Integer);
  5077. var
  5078.   I: Integer;
  5079.   K: PWordArray;
  5080.   A,B,C,D: Word;
  5081. begin
  5082.   Assert(Size = Context.BlockSize);
  5083.  
  5084.   K := FUser;
  5085.   A := PWordArray(Source)[0];
  5086.   B := PWordArray(Source)[1];
  5087.   C := PWordArray(Source)[2];
  5088.   D := PWordArray(Source)[3];
  5089.   for I := 15 downto 0 do
  5090.   begin
  5091.     D := D shr 5 or D shl 11 - (A and not C) - (B and C) - K[I * 4 +3];
  5092.     C := C shr 3 or C shl 13 - (D and not B) - (A and B) - K[I * 4 +2];
  5093.     B := B shr 2 or B shl 14 - (C and not A) - (D and A) - K[I * 4 +1];
  5094.     A := A shr 1 or A shl 15 - (B and not D) - (C and D) - K[I * 4 +0];
  5095.     if I in [5, 11] then
  5096.     begin
  5097.       Dec(D, K[C and $3F]);
  5098.       Dec(C, K[B and $3F]);
  5099.       Dec(B, K[A and $3F]);
  5100.       Dec(A, K[D and $3F]);
  5101.     end;
  5102.   end;
  5103.   PWordArray(Dest)[0] := A;
  5104.   PWordArray(Dest)[1] := B;
  5105.   PWordArray(Dest)[2] := C;
  5106.   PWordArray(Dest)[3] := D;
  5107. end;
  5108.  
  5109. // .TCipher_RC5
  5110. class function TCipher_RC5.Context: TCipherContext;
  5111. begin
  5112.   Result.KeySize := 256;
  5113.   Result.BlockSize := 8;
  5114.   Result.BufferSize := 8;
  5115.   Result.UserSize := 136;
  5116.   Result.UserSave := False;
  5117. end;
  5118.  
  5119. procedure TCipher_RC5.SetRounds(Value: Integer);
  5120. begin
  5121.   if Value <> FRounds then
  5122.   begin
  5123.     if not (FState in [csNew, csInitialized, csDone]) then Done;
  5124.     if Value <= 0 then Value := 12;
  5125.     FRounds := Value;
  5126.   end;
  5127. end;
  5128.  
  5129. procedure TCipher_RC5.DoInit(const Key; Size: Integer);
  5130. var
  5131.   K: array[0..63] of LongWord;
  5132.   L,Z,I,J: Integer;
  5133.   D: PLongArray;
  5134.   A,B,T: LongWord;
  5135. begin
  5136.   if FRounds <= 0 then FRounds := 12;
  5137.   FillChar(K, SizeOf(K), 0);
  5138.   Move(Key, K, Size);
  5139.   D := FUser;
  5140.   L := (Size +3) shr 2;
  5141.   if L <= 0 then L := 1;
  5142.   T := $B7E15163;
  5143.   for I := 0 to (FRounds + 1) * 2 do
  5144.   begin
  5145.     D[I] := T;
  5146.     Inc(T, $9E3779B9);
  5147.   end;
  5148.   if L > (FRounds + 1) * 2 then Z := L * 3
  5149.     else Z := (FRounds + 1) * 6;
  5150.   I := 0;
  5151.   J := 0;
  5152.   A := 0;
  5153.   B := 0;
  5154.   for Z := Z downto 1 do
  5155.   begin
  5156.     A := D[I] + A + B;
  5157.     A := A shl 3 or A shr 29;
  5158.     D[I] := A;
  5159.     T := A + B;
  5160.     B := K[J] + T;
  5161.     B := B shl T or B shr (32 - T);
  5162.     K[J] := B;
  5163.     I := (I + 1) mod ((FRounds + 1) * 2);
  5164.     J := (J + 1) mod L;
  5165.   end;
  5166.   ProtectBuffer(K, SizeOf(K));
  5167. end;
  5168.  
  5169. procedure TCipher_RC5.DoEncode(Source, Dest: Pointer; Size: Integer);
  5170. var
  5171.   K: PLongArray;
  5172.   I: Integer;
  5173.   A,B: LongWord;
  5174. begin
  5175.   Assert(Size = Context.BufferSize);
  5176.  
  5177.   K := FUser;
  5178.   A := PLongArray(Source)[0] + K[0];
  5179.   B := PLongArray(Source)[1] + K[1];
  5180.   for I := 1 to FRounds do
  5181.   begin
  5182.     A := A xor B; A := A shl B or A shr (32 - B) + K[I * 2 +0];
  5183.     B := B xor A; B := B shl A or B shr (32 - A) + K[I * 2 +1];
  5184.   end;
  5185.   PLongArray(Dest)[0] := A;
  5186.   PLongArray(Dest)[1] := B;
  5187. end;
  5188.  
  5189. procedure TCipher_RC5.DoDecode(Source, Dest: Pointer; Size: Integer);
  5190. var
  5191.   K: PLongArray;
  5192.   I: Integer;
  5193.   A,B: LongWord;
  5194. begin
  5195.   Assert(Size = Context.BufferSize);
  5196.  
  5197.   K := @PLongArray(FUser)[0];
  5198.   A := PLongArray(Source)[0];
  5199.   B := PLongArray(Source)[1];
  5200.   for I := FRounds downto 1 do
  5201.   begin
  5202.     B := B - K[I * 2 +1]; B := B shr A or B shl (32 - A) xor A;
  5203.     A := A - K[I * 2 +0]; A := A shr B or A shl (32 - B) xor B;
  5204.   end;
  5205.   PLongArray(Dest)[0] := A - K[0];
  5206.   PLongArray(Dest)[1] := B - K[1];
  5207. end;
  5208.  
  5209. // .TCipher_SAFER
  5210. class function TCipher_SAFER.Context: TCipherContext;
  5211. begin
  5212.   Result.KeySize := 16;
  5213.   Result.BlockSize := 8;
  5214.   Result.BufferSize := 8;
  5215.   Result.UserSize := 768;
  5216.   Result.UserSave := False;
  5217. end;
  5218.  
  5219. procedure TCipher_SAFER.SetRounds(Value: Integer);
  5220. begin
  5221.   if not (FState in [csNew, csInitialized, csDone]) then Done;
  5222.   if (Value < 4) or (Value > 13) then
  5223.     case FVersion of  {Default Rounds}
  5224.       svK40, svSK40: Value := 5;
  5225.       svK64, svSK64: Value := 6;
  5226.       svK128, svSK128: Value := 10;
  5227.     else
  5228.       Value := 8;
  5229.     end;
  5230.   FRounds := Value;
  5231. end;
  5232.  
  5233. procedure TCipher_SAFER.SetVersion(Value: TSAFERVersion);
  5234. begin
  5235.   if Value <> FVersion then
  5236.   begin
  5237.     if not (FState in [csNew, csInitialized, csDone]) then Done;
  5238.     FVersion := Value;
  5239.     SetRounds(0);
  5240.   end;
  5241. end;
  5242.  
  5243. procedure TCipher_SAFER.DoInit(const Key; Size: Integer);
  5244.  
  5245.   procedure InitTab;
  5246.   var
  5247.     I,E: Integer;
  5248.     Exp: PByteArray;
  5249.     Log: PByteArray;
  5250.   begin
  5251.     Exp := FUser;
  5252.     Log := @Exp[256];
  5253.     E   := 1;
  5254.     for I := 0 to 255 do
  5255.     begin
  5256.       Exp[I] := E and $FF;
  5257.       Log[E and $FF] := I;
  5258.       E := (E * 45) mod 257;
  5259.     end;
  5260.   end;
  5261.  
  5262.   procedure InitKey;
  5263.   var
  5264.     D: PByte;
  5265.     Exp: PByteArray;
  5266.     Strong: Boolean;
  5267.     K: array[Boolean, 0..8] of Byte;
  5268.     I,J: Integer;
  5269.   begin
  5270.     Strong := FVersion in [svSK40, svSK64, svSK128];
  5271.     Exp := FUser;
  5272.     D := @Exp[512];
  5273.     FillChar(K, SizeOf(K), 0);
  5274. {Setup Key A}
  5275.     I := Size;
  5276.     if I > 8 then I := 8;
  5277.     Move(Key, K[False], I);
  5278. {Setup the Key for K-40, SK-40}
  5279.     if FVersion in [svK40, svSK40] then
  5280.     begin
  5281.       K[False, 5] := K[False, 0] xor K[False, 2] xor 129;
  5282.       K[False, 6] := K[False, 0] xor K[False, 3] xor K[False, 4] xor 66;
  5283.       K[False, 7] := K[False, 1] xor K[False, 2] xor K[False, 4] xor 36;
  5284.       K[False, 8] := K[False, 1] xor K[False, 3] xor 24;
  5285.       Move(K[False], K[True], SizeOf(K[False]));
  5286.     end else
  5287.     begin
  5288.       if Size > 8 then
  5289.       begin
  5290.         I := Size - 8;
  5291.         if I > 8 then I := 8;
  5292.         Move(TByteArray(Key)[8], K[True], I);
  5293.       end else Move(K[False], K[True], 9);
  5294.       for I := 0 to 7 do
  5295.       begin
  5296.         K[False, 8] := K[False, 8] xor K[False, I];
  5297.         K[True, 8]  := K[True, 8]  xor K[True, I];
  5298.       end;
  5299.     end;
  5300. {Setup the KeyData}
  5301.     Move(K[True], D^, 8);
  5302.     Inc(D, 8);
  5303.  
  5304.     for I := 0 to 8 do
  5305.       K[False, I] := K[False, I] shr 3 or K[False, I] shl 5;
  5306.  
  5307.     for I := 1 to FRounds do
  5308.     begin
  5309.       for J := 0 to 8 do
  5310.       begin
  5311.         K[False, J] := K[False, J] shl 6 or K[False, J] shr 2;
  5312.         K[True, J] := K[True, J] shl 6 or K[True, J] shr 2;
  5313.       end;
  5314.       for J := 0 to 7 do
  5315.       begin
  5316.         if Strong then D^ := K[False, (J + I * 2 -1) mod 9] + Exp[Exp[18 * I + J +1]]
  5317.           else D^ := K[False, J] + Exp[Exp[18 * I + J +1]];
  5318.         Inc(D);
  5319.       end;
  5320.       for J := 0 to 7 do
  5321.       begin
  5322.         if Strong then D^ := K[True, (J + I * 2) mod 9] + Exp[Exp[18 * I + J +10]]
  5323.           else D^ := K[True, J] + Exp[Exp[18 * I + J +10]];
  5324.         Inc(D);
  5325.       end;
  5326.     end;
  5327.     ProtectBuffer(K, SizeOf(K));
  5328.   end;
  5329.  
  5330. begin
  5331.   if (FRounds < 4) or (FRounds > 13) then
  5332.     case FVersion of
  5333.       svK40, svSK40: FRounds := 5;
  5334.       svK64, svSK64: FRounds := 6;
  5335.       svK128, svSK128: FRounds := 10;
  5336.     else
  5337.       FRounds := 8;
  5338.     end;
  5339.   InitTab;
  5340.   InitKey;
  5341. end;
  5342.  
  5343. procedure TCipher_SAFER.DoEncode(Source, Dest: Pointer; Size: Integer);
  5344. var
  5345.   Exp,Log,Key: PByteArray;
  5346.   I: Integer;
  5347.   A,B,C,D,E,F,G,H,T: Byte;
  5348. begin
  5349.   Assert(Size = Context.BufferSize);
  5350.  
  5351.   Exp := FUser;
  5352.   Log := @Exp[256];
  5353.   Key := @Exp[512];
  5354.   A := PByteArray(Source)[0];
  5355.   B := PByteArray(Source)[1];
  5356.   C := PByteArray(Source)[2];
  5357.   D := PByteArray(Source)[3];
  5358.   E := PByteArray(Source)[4];
  5359.   F := PByteArray(Source)[5];
  5360.   G := PByteArray(Source)[6];
  5361.   H := PByteArray(Source)[7];
  5362.   for I := 0 to FRounds -1 do
  5363.   begin
  5364.     A := A xor Key[0];
  5365.     B := B  +  Key[1];
  5366.     C := C  +  Key[2];
  5367.     D := D xor Key[3];
  5368.     E := E xor Key[4];
  5369.     F := F  +  Key[5];
  5370.     G := G  +  Key[6];
  5371.     H := H xor Key[7];
  5372.     A := Exp[A]  +  Key[8];
  5373.     B := Log[B] xor Key[9];
  5374.     C := Log[C] xor Key[10];
  5375.     D := Exp[D]  +  Key[11];
  5376.     E := Exp[E]  +  Key[12];
  5377.     F := Log[F] xor Key[13];
  5378.     G := Log[G] xor Key[14];
  5379.     H := Exp[H]  +  Key[15];
  5380.     Inc(B, A); Inc(A, B);
  5381.     Inc(D, C); Inc(C, D);
  5382.     Inc(F, E); Inc(E, F);
  5383.     Inc(H, G); Inc(G, H);
  5384.     Inc(C, A); Inc(A, C);
  5385.     Inc(G, E); Inc(E, G);
  5386.     Inc(D, B); Inc(B, D);
  5387.     Inc(H, F); Inc(F, H);
  5388.     Inc(E, A); Inc(A, E);
  5389.     Inc(F, B); Inc(B, F);
  5390.     Inc(G, C); Inc(C, G);
  5391.     Inc(H, D); Inc(D, H);
  5392.     T := B; B := E; E := C; C := T;
  5393.     T := D; D := F; F := G; G := T;
  5394.     Key := @Key[16];
  5395.   end;
  5396.   PByteArray(Dest)[0] := A xor Key[0];
  5397.   PByteArray(Dest)[1] := B  +  Key[1];
  5398.   PByteArray(Dest)[2] := C  +  Key[2];
  5399.   PByteArray(Dest)[3] := D xor Key[3];
  5400.   PByteArray(Dest)[4] := E xor Key[4];
  5401.   PByteArray(Dest)[5] := F  +  Key[5];
  5402.   PByteArray(Dest)[6] := G  +  Key[6];
  5403.   PByteArray(Dest)[7] := H xor Key[7];
  5404. end;
  5405.  
  5406. procedure TCipher_SAFER.DoDecode(Source, Dest: Pointer; Size: Integer);
  5407. var
  5408.   Exp,Log,Key: PByteArray;
  5409.   I: Integer;
  5410.   A,B,C,D,E,F,G,H,T: Byte;
  5411. begin
  5412.   Assert(Size = Context.BufferSize);
  5413.  
  5414.   Exp := FUser;
  5415.   Log := @Exp[256];
  5416.   Key := @Exp[504 + 8 * (FRounds * 2 + 1)];
  5417.   A := PByteArray(Source)[0] xor Key[0];
  5418.   B := PByteArray(Source)[1]  -  Key[1];
  5419.   C := PByteArray(Source)[2]  -  Key[2];
  5420.   D := PByteArray(Source)[3] xor Key[3];
  5421.   E := PByteArray(Source)[4] xor Key[4];
  5422.   F := PByteArray(Source)[5]  -  Key[5];
  5423.   G := PByteArray(Source)[6]  -  Key[6];
  5424.   H := PByteArray(Source)[7] xor Key[7];
  5425.   for I := 0 to FRounds -1 do
  5426.   begin
  5427.     Dec(PByte(Key), 16);
  5428.     T := E; E := B; B := C; C := T;
  5429.     T := F; F := D; D := G; G := T;
  5430.     Dec(A, E); Dec(E, A);
  5431.     Dec(B, F); Dec(F, B);
  5432.     Dec(C, G); Dec(G, C);
  5433.     Dec(D, H); Dec(H, D);
  5434.     Dec(A, C); Dec(C, A);
  5435.     Dec(E, G); Dec(G, E);
  5436.     Dec(B, D); Dec(D, B);
  5437.     Dec(F, H); Dec(H, F);
  5438.     Dec(A, B); Dec(B, A);
  5439.     Dec(C, D); Dec(D, C);
  5440.     Dec(E, F); Dec(F, E);
  5441.     Dec(G, H); Dec(H, G);
  5442.     H := H  -  Key[15];
  5443.     G := G xor Key[14];
  5444.     F := F xor Key[13];
  5445.     E := E  -  Key[12];
  5446.     D := D  -  Key[11];
  5447.     C := C xor Key[10];
  5448.     B := B xor Key[9];
  5449.     A := A  -  Key[8];
  5450.     H := Log[H] xor Key[7];
  5451.     G := Exp[G]  -  Key[6];
  5452.     F := Exp[F]  -  Key[5];
  5453.     E := Log[E] xor Key[4];
  5454.     D := Log[D] xor Key[3];
  5455.     C := Exp[C]  -  Key[2];
  5456.     B := Exp[B]  -  Key[1];
  5457.     A := Log[A] xor Key[0];
  5458.   end;
  5459.   PByteArray(Dest)[0] := A;
  5460.   PByteArray(Dest)[1] := B;
  5461.   PByteArray(Dest)[2] := C;
  5462.   PByteArray(Dest)[3] := D;
  5463.   PByteArray(Dest)[4] := E;
  5464.   PByteArray(Dest)[5] := F;
  5465.   PByteArray(Dest)[6] := G;
  5466.   PByteArray(Dest)[7] := H;
  5467. end;
  5468.  
  5469. // .TCipher_Shark
  5470. type
  5471.   PLong64 = ^TLong64;
  5472.   TLong64  = packed record
  5473.                L,R: LongWord;
  5474.              end;
  5475.  
  5476.   PLong64Array = ^TLong64Array;
  5477.   TLong64Array = array[0..1023] of TLong64;
  5478.  
  5479. class function TCipher_Shark.Context: TCipherContext;
  5480. begin
  5481.   Result.KeySize := 16;
  5482.   Result.BlockSize := 8;
  5483.   Result.BufferSize := 8;
  5484.   Result.UserSize := 112;
  5485.   Result.UserSave := False;
  5486. end;
  5487.  
  5488. procedure TCipher_Shark.DoInit(const Key; Size: Integer);
  5489. var
  5490.   Log, ALog: array[0..255] of Byte;
  5491.  
  5492.   procedure InitLog;
  5493.   var
  5494.     I, J: Word;
  5495.   begin
  5496.     ALog[0] := 1;
  5497.     for I := 1 to 255 do
  5498.     begin
  5499.       J := ALog[I-1] shl 1;
  5500.       if J and $100 <> 0 then J := J xor $01F5;
  5501.       ALog[I] := J;
  5502.     end;
  5503.     for I := 1 to 254 do Log[ALog[I]] := I;
  5504.   end;
  5505.  
  5506.   function Transform(A: TLong64): TLong64;
  5507.  
  5508.     function Mul(A, B: Integer): Byte;
  5509.     begin
  5510.       Result := ALog[(Log[A] + Log[B]) mod 255];
  5511.     end;
  5512.  
  5513.   var
  5514.     I,J: Byte;
  5515.     K,T: array[0..7] of Byte;
  5516.   begin
  5517.     Move(A.R, K[0], 4);
  5518.     Move(A.L, K[4], 4);
  5519.     SwapLongBuffer(K, K, 2);
  5520.     for I := 0 to 7 do
  5521.     begin
  5522.       T[I] := Mul(Shark_I[I, 0], K[0]);
  5523.       for J := 1 to 7 do T[I] := T[I] xor Mul(Shark_I[I, J], K[J]);
  5524.     end;
  5525.     Result.L := T[0];
  5526.     Result.R := 0;
  5527.     for I := 1 to 7 do
  5528.     begin
  5529.       Result.R := Result.R shl 8 or Result.L shr 24;
  5530.       Result.L := Result.L shl 8 xor T[I];
  5531.     end;
  5532.   end;
  5533.  
  5534.   function Shark(D: TLong64; K: PLong64): TLong64;
  5535.   var
  5536.     R,T: Integer;
  5537.   begin
  5538.     for R := 0 to 4 do
  5539.     begin
  5540.       D.L := D.L xor K.L;
  5541.       D.R := D.R xor K.R;
  5542.       Inc(K);
  5543.       T   := Shark_CE[0, D.R shr 23 and $1FE] xor
  5544.              Shark_CE[1, D.R shr 15 and $1FE] xor
  5545.              Shark_CE[2, D.R shr  7 and $1FE] xor
  5546.              Shark_CE[3, D.R shl  1 and $1FE] xor
  5547.              Shark_CE[4, D.L shr 23 and $1FE] xor
  5548.              Shark_CE[5, D.L shr 15 and $1FE] xor
  5549.              Shark_CE[6, D.L shr  7 and $1FE] xor
  5550.              Shark_CE[7, D.L shl  1 and $1FE];
  5551.  
  5552.       D.R := Shark_CE[0, D.R shr 23 and $1FE or 1] xor
  5553.              Shark_CE[1, D.R shr 15 and $1FE or 1] xor
  5554.              Shark_CE[2, D.R shr  7 and $1FE or 1] xor
  5555.              Shark_CE[3, D.R shl  1 and $1FE or 1] xor
  5556.              Shark_CE[4, D.L shr 23 and $1FE or 1] xor
  5557.              Shark_CE[5, D.L shr 15 and $1FE or 1] xor
  5558.              Shark_CE[6, D.L shr  7 and $1FE or 1] xor
  5559.              Shark_CE[7, D.L shl  1 and $1FE or 1];
  5560.       D.L := T;
  5561.     end;
  5562.     D.L := D.L xor K.L;
  5563.     D.R := D.R xor K.R;
  5564.     Inc(K);
  5565.     D.L := LongWord(Shark_SE[D.L shr 24 and $FF]) shl 24 xor
  5566.            LongWord(Shark_SE[D.L shr 16 and $FF]) shl 16 xor
  5567.            LongWord(Shark_SE[D.L shr  8 and $FF]) shl  8 xor
  5568.            LongWord(Shark_SE[D.L        and $FF]);
  5569.     D.R := LongWord(Shark_SE[D.R shr 24 and $FF]) shl 24 xor
  5570.            LongWord(Shark_SE[D.R shr 16 and $FF]) shl 16 xor
  5571.            LongWord(Shark_SE[D.R shr  8 and $FF]) shl  8 xor
  5572.            LongWord(Shark_SE[D.R        and $FF]);
  5573.     Result.L := D.L xor K.L;
  5574.     Result.R := D.R xor K.R;
  5575.   end;
  5576.  
  5577. var
  5578.   T: array[0..6] of TLong64;
  5579.   A: array[0..6] of TLong64;
  5580.   K: array[0..15] of Byte;
  5581.   I,J,R: Byte;
  5582.   E,D: PLong64Array;
  5583.   L: TLong64;
  5584. begin
  5585.   FillChar(K, SizeOf(K), 0);
  5586.   Move(Key, K, Size);
  5587.   InitLog;
  5588.   E := FUser;
  5589.   D := @E[7];
  5590.   Move(Shark_CE[0], T, SizeOf(T));
  5591.   T[6] := Transform(T[6]);
  5592.   I := 0;
  5593.   for R := 0 to 6 do
  5594.   begin
  5595.     Inc(I);
  5596.     A[R].L := K[I and $F];
  5597.     A[R].R := 0;
  5598.     for J := 1 to 7 do
  5599.     begin
  5600.       Inc(I);
  5601.       A[R].R := A[R].R shl 8 or A[R].L shr 24;
  5602.       A[R].L := A[R].L shl 8 or K[I and $F];
  5603.     end;
  5604.   end;
  5605.   L.L := 0;
  5606.   L.R := 0;
  5607.   L := Shark(L, @T);
  5608.   E[0].L := A[0].L xor L.L;
  5609.   E[0].R := A[0].R xor L.R;
  5610.   for R := 1 to 6 do
  5611.   begin
  5612.     L := Shark(E[R - 1], @T);
  5613.     E[R].L := A[R].L xor L.L;
  5614.     E[R].R := A[R].R xor L.R;
  5615.   end;
  5616.   E[6] := Transform(E[6]);
  5617.   D[0] := E[6];
  5618.   D[6] := E[0];
  5619.   for R := 1 to 5 do
  5620.     D[R] := Transform(E[6-R]);
  5621.   ProtectBuffer(Log, SizeOf(Log));
  5622.   ProtectBuffer(ALog, SizeOf(ALog));
  5623.   ProtectBuffer(T, SizeOf(T));
  5624.   ProtectBuffer(A, SizeOf(A));
  5625.   ProtectBuffer(K, SizeOf(K));
  5626. end;
  5627.  
  5628. procedure TCipher_Shark.DoEncode(Source, Dest: Pointer; Size: Integer);
  5629. var
  5630.   I: Integer;
  5631.   T,L,R: LongWord;
  5632.   K: PLongArray;
  5633. begin
  5634.   Assert(Size = Context.BufferSize);
  5635.  
  5636.   K := FUser;
  5637.   L := PLong64(Source).L;
  5638.   R := PLong64(Source).R;
  5639.   for I := 0 to 4 do
  5640.   begin
  5641.     L := L xor K[I * 2 +0];
  5642.     R := R xor K[I * 2 +1];
  5643.     T := Shark_CE[0, R shr 23 and $1FE] xor
  5644.          Shark_CE[1, R shr 15 and $1FE] xor
  5645.          Shark_CE[2, R shr  7 and $1FE] xor
  5646.          Shark_CE[3, R shl  1 and $1FE] xor
  5647.          Shark_CE[4, L shr 23 and $1FE] xor
  5648.          Shark_CE[5, L shr 15 and $1FE] xor
  5649.          Shark_CE[6, L shr  7 and $1FE] xor
  5650.          Shark_CE[7, L shl  1 and $1FE];
  5651.     R := Shark_CE[0, R shr 23 and $1FE or 1] xor
  5652.          Shark_CE[1, R shr 15 and $1FE or 1] xor
  5653.          Shark_CE[2, R shr  7 and $1FE or 1] xor
  5654.          Shark_CE[3, R shl  1 and $1FE or 1] xor
  5655.          Shark_CE[4, L shr 23 and $1FE or 1] xor
  5656.          Shark_CE[5, L shr 15 and $1FE or 1] xor
  5657.          Shark_CE[6, L shr  7 and $1FE or 1] xor
  5658.          Shark_CE[7, L shl  1 and $1FE or 1];
  5659.     L := T;
  5660.   end;
  5661.   L := L xor K[10];
  5662.   R := R xor K[11];
  5663.   L := LongWord(Shark_SE[L shr 24        ]) shl 24 xor
  5664.        LongWord(Shark_SE[L shr 16 and $FF]) shl 16 xor
  5665.        LongWord(Shark_SE[L shr  8 and $FF]) shl  8 xor
  5666.        LongWord(Shark_SE[L        and $FF]);
  5667.   R := LongWord(Shark_SE[R shr 24        ]) shl 24 xor
  5668.        LongWord(Shark_SE[R shr 16 and $FF]) shl 16 xor
  5669.        LongWord(Shark_SE[R shr  8 and $FF]) shl  8 xor
  5670.        LongWord(Shark_SE[R        and $FF]);
  5671.   PLong64(Dest).L := L xor K[12];
  5672.   PLong64(Dest).R := R xor K[13];
  5673. end;
  5674.  
  5675. procedure TCipher_Shark.DoDecode(Source, Dest: Pointer; Size: Integer);
  5676. var
  5677.   I: Integer;
  5678.   T,R,L: LongWord;
  5679.   K: PLongArray;
  5680. begin
  5681.   Assert(Size = Context.BufferSize);
  5682.  
  5683.   K := @PLongArray(FUser)[14];
  5684.   L := PLong64(Source).L;
  5685.   R := PLong64(Source).R;
  5686.   for I := 0 to 4 do
  5687.   begin
  5688.     L := L xor K[I * 2 +0];
  5689.     R := R xor K[I * 2 +1];
  5690.     T := Shark_CD[0, R shr 23 and $1FE] xor
  5691.          Shark_CD[1, R shr 15 and $1FE] xor
  5692.          Shark_CD[2, R shr  7 and $1FE] xor
  5693.          Shark_CD[3, R shl  1 and $1FE] xor
  5694.          Shark_CD[4, L shr 23 and $1FE] xor
  5695.          Shark_CD[5, L shr 15 and $1FE] xor
  5696.          Shark_CD[6, L shr  7 and $1FE] xor
  5697.          Shark_CD[7, L shl  1 and $1FE];
  5698.     R := Shark_CD[0, R shr 23 and $1FE or 1] xor
  5699.          Shark_CD[1, R shr 15 and $1FE or 1] xor
  5700.          Shark_CD[2, R shr  7 and $1FE or 1] xor
  5701.          Shark_CD[3, R shl  1 and $1FE or 1] xor
  5702.          Shark_CD[4, L shr 23 and $1FE or 1] xor
  5703.          Shark_CD[5, L shr 15 and $1FE or 1] xor
  5704.          Shark_CD[6, L shr  7 and $1FE or 1] xor
  5705.          Shark_CD[7, L shl  1 and $1FE or 1];
  5706.     L := T;
  5707.   end;
  5708.   L := L xor K[10];
  5709.   R := R xor K[11];
  5710.   L := LongWord(Shark_SD[L shr 24        ]) shl 24 xor
  5711.        LongWord(Shark_SD[L shr 16 and $FF]) shl 16 xor
  5712.        LongWord(Shark_SD[L shr  8 and $FF]) shl  8 xor
  5713.        LongWord(Shark_SD[L        and $FF]);
  5714.   R := LongWord(Shark_SD[R shr 24        ]) shl 24 xor
  5715.        LongWord(Shark_SD[R shr 16 and $FF]) shl 16 xor
  5716.        LongWord(Shark_SD[R shr  8 and $FF]) shl  8 xor
  5717.        LongWord(Shark_SD[R        and $FF]);
  5718.   PLong64(Dest).L := L xor K[12];
  5719.   PLong64(Dest).R := R xor K[13];
  5720. end;
  5721.  
  5722.  
  5723. // .TCipher_Skipjack
  5724. type
  5725.   PSkipjackTab = ^TSkipjackTab;
  5726.   TSkipjackTab = array[0..255] of Byte;
  5727.  
  5728. class function TCipher_Skipjack.Context: TCipherContext;
  5729. begin
  5730.   Result.KeySize := 10;
  5731.   Result.BlockSize := 8;
  5732.   Result.BufferSize := 8;
  5733.   Result.UserSize := $A00;
  5734.   Result.UserSave := False;
  5735. end;
  5736.  
  5737. procedure TCipher_Skipjack.DoInit(const Key; Size: Integer);
  5738. var
  5739.   K: array[0..9] of Byte;
  5740.   D: PByte;
  5741.   I,J: Integer;
  5742. begin
  5743.   FillChar(K, SizeOf(K), 0);
  5744.   Move(Key, K, Size);
  5745.   D := FUser;
  5746.   for I := 0 to 9 do
  5747.     for J := 0 to 255 do
  5748.     begin
  5749.       D^ := Skipjack_Data[J xor K[I]];
  5750.       Inc(D);
  5751.     end;
  5752.   ProtectBuffer(K, SizeOf(K));
  5753. end;
  5754.  
  5755. procedure TCipher_Skipjack.DoEncode(Source, Dest: Pointer; Size: Integer);
  5756. var
  5757.   Tab,Min: PSkipjackTab;
  5758.   Max: PChar;
  5759.   K,T,A,B,C,D: LongWord;
  5760. begin
  5761.   Assert(Size = Context.BufferSize);
  5762.  
  5763.   Min := FUser;
  5764.   Max := PChar(Min) + 9 * 256;
  5765.   Tab := Min;
  5766.   A   := Swap(PWordArray(Source)[0]);
  5767.   B   := Swap(PWordArray(Source)[1]);
  5768.   C   := Swap(PWordArray(Source)[2]);
  5769.   D   := Swap(PWordArray(Source)[3]);
  5770.   K   := 0;
  5771.   repeat
  5772.     Inc(K);
  5773.     T := A;
  5774.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5775.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5776.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5777.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5778.     A := T xor D xor K;
  5779.     D := C;
  5780.     C := B;
  5781.     B := T;
  5782.   until K = 8;
  5783.   repeat
  5784.     Inc(K);
  5785.     T := A;
  5786.     A := D;
  5787.     D := C;
  5788.     C := T xor B xor K;
  5789.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5790.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5791.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5792.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5793.     B := T;
  5794.   until K = 16;
  5795.   repeat
  5796.     Inc(K);
  5797.     T := A;
  5798.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5799.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5800.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5801.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5802.     A := T xor D xor K;
  5803.     D := C;
  5804.     C := B;
  5805.     B := T;
  5806.   until K = 24;
  5807.   repeat
  5808.     Inc(K);
  5809.     T := A;
  5810.     A := D;
  5811.     D := C;
  5812.     C := T xor B xor K;
  5813.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5814.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5815.     T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
  5816.     T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
  5817.     B := T;
  5818.   until K = 32;
  5819.   PWordArray(Dest)[0] := Swap(A);
  5820.   PWordArray(Dest)[1] := Swap(B);
  5821.   PWordArray(Dest)[2] := Swap(C);
  5822.   PWordArray(Dest)[3] := Swap(D);
  5823. end;
  5824.  
  5825. procedure TCipher_Skipjack.DoDecode(Source, Dest: Pointer; Size: Integer);
  5826. var
  5827.   Tab,Max: PSkipjackTab;
  5828.   Min: PChar;
  5829.   K,T,A,B,C,D: LongWord;
  5830. begin
  5831.   Assert(Size = Context.BufferSize);
  5832.  
  5833.   Min := FUser;
  5834.   Max := Pointer(Min + 9 * 256);
  5835.   Tab := Pointer(Min + 7 * 256);
  5836.   A   := Swap(PWordArray(Source)[0]); {holds as Integer, Compiler make faster Code}
  5837.   B   := Swap(PWordArray(Source)[1]);
  5838.   C   := Swap(PWordArray(Source)[2]);
  5839.   D   := Swap(PWordArray(Source)[3]);
  5840.   K   := 32;
  5841.   repeat
  5842.     T := B;
  5843.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5844.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5845.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5846.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5847.     B := T xor C xor K;
  5848.     C := D;
  5849.     D := A;
  5850.     A := T;
  5851.     Dec(K);
  5852.   until K = 24;
  5853.   repeat
  5854.     T := B;
  5855.     B := C;
  5856.     C := D;
  5857.     D := T xor A xor K;
  5858.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5859.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5860.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5861.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5862.     A := T;
  5863.     Dec(K);
  5864.   until K = 16;
  5865.   repeat
  5866.     T := B;
  5867.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5868.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5869.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5870.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5871.     B := C xor T xor K;
  5872.     C := D;
  5873.     D := A;
  5874.     A := T;
  5875.     Dec(K);
  5876.   until K = 8;
  5877.   repeat
  5878.     T := B;
  5879.     B := C;
  5880.     C := D;
  5881.     D := T xor A xor K;
  5882.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5883.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5884.     T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
  5885.     T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
  5886.     A := T;
  5887.     Dec(K);
  5888.   until K = 0;
  5889.   PWordArray(Dest)[0] := Swap(A);
  5890.   PWordArray(Dest)[1] := Swap(B);
  5891.   PWordArray(Dest)[2] := Swap(C);
  5892.   PWordArray(Dest)[3] := Swap(D);
  5893. end;
  5894.  
  5895.  
  5896. // .TCipher_TEA
  5897. const
  5898.   TEA_Delta = $9E3779B9;
  5899.  
  5900. class function TCipher_TEA.Context: TCipherContext;
  5901. begin
  5902.   Result.KeySize := 16;
  5903.   Result.BlockSize := 8;
  5904.   Result.BufferSize := 8;
  5905.   Result.UserSize := 32;
  5906.   Result.UserSave := False;
  5907. end;
  5908.  
  5909. procedure TCipher_TEA.SetRounds(Value: Integer);
  5910. begin
  5911.   if not (FState in [csNew, csInitialized, csDone]) then Done;
  5912.   if Value < 16 then Value := 16 else
  5913.     if Value > 32 then Value := 32;
  5914.   FRounds := Value;
  5915. end;
  5916.  
  5917. procedure TCipher_TEA.DoInit(const Key; Size: Integer);
  5918. begin
  5919.   Move(Key, FUser^, Size);
  5920.   SetRounds(FRounds);
  5921. end;
  5922.  
  5923. procedure TCipher_TEA.DoEncode(Source, Dest: Pointer; Size: Integer);
  5924. var
  5925.   I: Integer;
  5926.   Sum,X,Y,A,B,C,D: LongWord;
  5927. begin
  5928.   Assert(Size = Context.BufferSize);
  5929.  
  5930.   Sum := 0;
  5931.   A := PLongArray(FUser)[0];
  5932.   B := PLongArray(FUser)[1];
  5933.   C := PLongArray(FUser)[2];
  5934.   D := PLongArray(FUser)[3];
  5935.   X := PLongArray(Source)[0];
  5936.   Y := PLongArray(Source)[1];
  5937.   for I := 0 to FRounds -1 do
  5938.   begin
  5939.     Inc(Sum, TEA_Delta);
  5940.     Inc(X, (((Y shl 4 + A) xor Y) + Sum) xor (Y shr 5 + B));
  5941.     Inc(Y, (((X shl 4 + C) xor X) + Sum) xor (X shr 5 + D));
  5942.   end;
  5943.   PLongArray(Dest)[0] := X;
  5944.   PLongArray(Dest)[1] := Y;
  5945. end;
  5946.  
  5947. procedure TCipher_TEA.DoDecode(Source, Dest: Pointer; Size: Integer);
  5948. var
  5949.   I: Integer;
  5950.   Sum,X,Y,A,B,C,D: LongWord;
  5951. begin
  5952.   Assert(Size = Context.BufferSize);
  5953.  
  5954.   Sum := TEA_Delta * LongWord(FRounds);
  5955.   A := PLongArray(FUser)[0];
  5956.   B := PLongArray(FUser)[1];
  5957.   C := PLongArray(FUser)[2];
  5958.   D := PLongArray(FUser)[3];
  5959.   X := PLongArray(Source)[0];
  5960.   Y := PLongArray(Source)[1];
  5961.   for I := 0 to FRounds -1 do
  5962.   begin
  5963.     Dec(Y, (X shl 4 + C) xor X + Sum xor (X shr 5 + D));
  5964.     Dec(X, (Y shl 4 + A) xor Y + Sum xor (Y shr 5 + B));
  5965.     Dec(Sum, TEA_Delta);
  5966.   end;
  5967.   PLongArray(Dest)[0] := X;
  5968.   PLongArray(Dest)[1] := Y;
  5969. end;
  5970.  
  5971. // .TCipher_TEAN
  5972. procedure TCipher_TEAN.DoEncode(Source, Dest: Pointer; Size: Integer);
  5973. var
  5974.   I,Sum,X,Y: LongWord;
  5975.   K: PLongArray;
  5976. begin
  5977.   Assert(Size = Context.BufferSize);
  5978.  
  5979.   Sum := 0;
  5980.   X := PLongArray(Source)[0];
  5981.   Y := PLongArray(Source)[1];
  5982.   K := FUser;
  5983.   for I := 0 to FRounds -1 do
  5984.   begin
  5985.     Inc(X, (Y shl 4 xor Y shr 5) + (Y xor Sum) + K[Sum and 3]);
  5986.     Inc(Sum, TEA_Delta);
  5987.     Inc(Y, (X shl 4 xor X shr 5) + (X xor Sum) + K[Sum shr 11 and 3]);
  5988.   end;
  5989.   PLongArray(Dest)[0] := X;
  5990.   PLongArray(Dest)[1] := Y;
  5991. end;
  5992.  
  5993. procedure TCipher_TEAN.DoDecode(Source, Dest: Pointer; Size: Integer);
  5994. var
  5995.   I: Integer;
  5996.   Sum,X,Y: LongWord;
  5997.   K: PLongArray;
  5998. begin
  5999.   Assert(Size = Context.BufferSize);
  6000.  
  6001.   Sum := TEA_Delta * LongWord(FRounds);
  6002.   X := PLongArray(Source)[0];
  6003.   Y := PLongArray(Source)[1];
  6004.   K := FUser;
  6005.   for I := 0 to FRounds -1 do
  6006.   begin
  6007.     Dec(Y, (X shl 4 xor X shr 5) + (X xor Sum) + K[Sum shr 11 and 3]);
  6008.     Dec(Sum, TEA_Delta);
  6009.     Dec(X, (Y shl 4 xor Y shr 5) + (Y xor Sum) + K[Sum and 3]);
  6010.   end;
  6011.   PLongArray(Dest)[0] := X;
  6012.   PLongArray(Dest)[1] := Y;
  6013. end;
  6014.  
  6015.  
  6016. end.
  6017.  
  6018.