home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 December / Chip_2002-12_cd1.bin / ctenari / Hytha / MultiHSH.exe / SR.RAR / SR / DCPCrypt / Ciphers / DCPtwofish.pas < prev   
Pascal/Delphi Source File  |  2002-07-08  |  20KB  |  575 lines

  1. {******************************************************************************}
  2. {* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
  3. {******************************************************************************}
  4. {* A binary compatible implementation of Twofish ******************************}
  5. {******************************************************************************}
  6. {* Copyright (c) 1999-2002 David Barton                                       *}
  7. {* Permission is hereby granted, free of charge, to any person obtaining a    *}
  8. {* copy of this software and associated documentation files (the "Software"), *}
  9. {* to deal in the Software without restriction, including without limitation  *}
  10. {* the rights to use, copy, modify, merge, publish, distribute, sublicense,   *}
  11. {* and/or sell copies of the Software, and to permit persons to whom the      *}
  12. {* Software is furnished to do so, subject to the following conditions:       *}
  13. {*                                                                            *}
  14. {* The above copyright notice and this permission notice shall be included in *}
  15. {* all copies or substantial portions of the Software.                        *}
  16. {*                                                                            *}
  17. {* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *}
  18. {* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *}
  19. {* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *}
  20. {* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *}
  21. {* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    *}
  22. {* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        *}
  23. {* DEALINGS IN THE SOFTWARE.                                                  *}
  24. {******************************************************************************}
  25. unit DCPtwofish;
  26.  
  27. interface
  28. uses
  29.   Classes, Sysutils, DCPcrypt2, DCPconst, DCPblockciphers;
  30.  
  31. const
  32.   INPUTWHITEN= 0;
  33.   OUTPUTWHITEN= 4;
  34.   NUMROUNDS= 16;
  35.   ROUNDSUBKEYS= (OUTPUTWHITEN + 4);
  36.   TOTALSUBKEYS= (ROUNDSUBKEYS + NUMROUNDS * 2);
  37.   RS_GF_FDBK= $14d;
  38.   MDS_GF_FDBK= $169;
  39.   SK_STEP= $02020202;
  40.   SK_BUMP= $01010101;
  41.   SK_ROTL= 9;
  42.  
  43. type
  44.   TDCP_twofish= class(TDCP_blockcipher128)
  45.   protected
  46.     SubKeys: array[0..TOTALSUBKEYS-1] of DWord;
  47.     sbox: array[0..3,0..255] of DWord;
  48.     procedure InitKey(const Key; Size: longword); override;
  49.   public
  50.     class function GetID: integer; override;
  51.     class function GetAlgorithm: string; override;
  52.     class function GetMaxKeySize: integer; override;
  53.     class function SelfTest: boolean; override;
  54.     procedure Burn; override;
  55.     procedure EncryptECB(const InData; var OutData); override;
  56.     procedure DecryptECB(const InData; var OutData); override;
  57.     constructor Create(AOwner: TComponent); override;
  58.   end;
  59.  
  60.  
  61. {******************************************************************************}
  62. {******************************************************************************}
  63. implementation
  64. {$R-}{$Q-}
  65. {$I DCPtwofish.inc}
  66.  
  67. var
  68.   MDS: array[0..3,0..255] of dword;
  69.   MDSDone: boolean;
  70.  
  71. class function TDCP_twofish.GetID: integer;
  72. begin
  73.   Result:= DCP_twofish;
  74. end;
  75.  
  76. class function TDCP_twofish.GetAlgorithm: string;
  77. begin
  78.   Result:= 'Twofish';
  79. end;
  80.  
  81. class function TDCP_twofish.GetMaxKeySize: integer;
  82. begin
  83.   Result:= 256;
  84. end;
  85.  
  86. class function TDCP_twofish.SelfTest: boolean;
  87. const
  88.   Out128: array[0..15] of byte=
  89.     ($5D,$9D,$4E,$EF,$FA,$91,$51,$57,$55,$24,$F1,$15,$81,$5A,$12,$E0);
  90.   Out192: array[0..15] of byte=
  91.     ($E7,$54,$49,$21,$2B,$EE,$F9,$F4,$A3,$90,$BD,$86,$0A,$64,$09,$41);
  92.   Out256: array[0..15] of byte=
  93.     ($37,$FE,$26,$FF,$1C,$F6,$61,$75,$F5,$DD,$F4,$C3,$3B,$97,$A2,$05);
  94. var
  95.   i: integer;
  96.   Key: array[0..31] of byte;
  97.   Block: array[0..15] of byte;
  98.   Cipher: TDCP_twofish;
  99. begin
  100.   Cipher:= TDCP_twofish.Create(nil);
  101.   FillChar(Key,Sizeof(Key),0);
  102.   FillChar(Block,Sizeof(Block),0);
  103.   for i:= 1 to 49 do
  104.   begin
  105.     Cipher.Init(Key,128,nil);
  106.     Move(Block,Key,16);
  107.     Cipher.EncryptECB(Block,Block);
  108.     Cipher.Burn;
  109.   end;
  110.   Result:= boolean(CompareMem(@Block,@Out128,16));
  111.   FillChar(Key,Sizeof(Key),0);
  112.   FillChar(Block,Sizeof(Block),0);
  113.   for i:= 1 to 49 do
  114.   begin
  115.     Cipher.Init(Key,192,nil);
  116.     Move(Key[0],Key[16],8);
  117.     Move(Block,Key,16);
  118.     Cipher.EncryptECB(Block,Block);
  119.     Cipher.Burn;
  120.   end;
  121.   Result:= Result and boolean(CompareMem(@Block,@Out192,16));
  122.   FillChar(Key,Sizeof(Key),0);
  123.   FillChar(Block,Sizeof(Block),0);
  124.   for i:= 1 to 49 do
  125.   begin
  126.     Cipher.Init(Key,256,nil);
  127.     Move(Key[0],Key[16],16);
  128.     Move(Block,Key,16);
  129.     Cipher.EncryptECB(Block,Block);
  130.     Cipher.Burn;
  131.   end;
  132.   Result:= Result and boolean(CompareMem(@Block,@Out256,16));
  133.   Cipher.Burn;
  134.   Cipher.Free;
  135. end;
  136.  
  137. function LFSR1(x: DWord): DWord;
  138. begin
  139.   if (x and 1)<> 0 then
  140.     Result:= (x shr 1) xor (MDS_GF_FDBK div 2)
  141.   else
  142.     Result:= (x shr 1);
  143. end;
  144. function LFSR2(x: DWord): DWord;
  145. begin
  146.   if (x and 2)<> 0 then
  147.     if (x and 1)<> 0 then
  148.       Result:= (x shr 2) xor (MDS_GF_FDBK div 2) xor (MDS_GF_FDBK div 4)
  149.     else
  150.       Result:= (x shr 2) xor (MDS_GF_FDBK div 2)
  151.   else
  152.     if (x and 1)<> 0 then
  153.       Result:= (x shr 2) xor (MDS_GF_FDBK div 4)
  154.     else
  155.       Result:= (x shr 2);
  156. end;
  157. function Mul_X(x: DWord): DWord;
  158. begin
  159.   Result:= x xor LFSR2(x);
  160. end;
  161. function Mul_Y(x: DWord): DWord;
  162. begin
  163.   Result:= x xor LFSR1(x) xor LFSR2(x);
  164. end;
  165.  
  166. function RS_MDS_Encode(lK0, lK1: DWord): DWord;
  167. var
  168.   lR, nJ, lG2, lG3: DWord;
  169.   bB: byte;
  170. begin
  171.   lR:= lK1;
  172.   for nJ:= 0 to 3 do
  173.   begin
  174.     bB:= lR shr 24;
  175.     if (bB and $80)<> 0 then
  176.       lG2:= ((bB shl 1) xor RS_GF_FDBK) and $FF
  177.     else
  178.       lG2:= (bB shl 1) and $FF;
  179.     if (bB and 1)<> 0 then
  180.       lG3:= ((bB shr 1) and $7f) xor (RS_GF_FDBK shr 1) xor lG2
  181.     else
  182.       lG3:= ((bB shr 1) and $7f) xor lG2;
  183.     lR:= (lR shl 8) xor (lG3 shl 24) xor (lG2 shl 16) xor (lG3 shl 8) xor bB;
  184.   end;
  185.   lR:= lR xor lK0;
  186.   for nJ:= 0 to 3 do
  187.   begin
  188.     bB:= lR shr 24;
  189.     if (bB and $80)<> 0 then
  190.       lG2:= ((bB shl 1) xor RS_GF_FDBK) and $FF
  191.     else
  192.       lG2:= (bB shl 1) and $FF;
  193.     if (bB and 1)<> 0 then
  194.       lG3:= ((bB shr 1) and $7f) xor (RS_GF_FDBK shr 1) xor lG2
  195.     else
  196.       lG3:= ((bB shr 1) and $7f) xor lG2;
  197.     lR:= (lR shl 8) xor (lG3 shl 24) xor (lG2 shl 16) xor (lG3 shl 8) xor bB;
  198.   end;
  199.   Result:= lR;
  200. end;
  201.  
  202. function f32(x: DWord; K32: PDWordArray; Len: DWord): DWord;
  203. var
  204.   t0, t1, t2, t3: DWord;
  205. begin
  206.   t0:= x and $FF;
  207.   t1:= (x shr 8) and $FF;
  208.   t2:= (x shr 16) and $FF;
  209.   t3:= x shr 24;
  210.   if Len= 256 then
  211.   begin
  212.     t0:= p8x8[1,t0] xor ((K32^[3]) and $FF);
  213.     t1:= p8x8[0,t1] xor ((K32^[3] shr  8) and $FF);
  214.     t2:= p8x8[0,t2] xor ((K32^[3] shr 16) and $FF);
  215.     t3:= p8x8[1,t3] xor ((K32^[3] shr 24));
  216.   end;
  217.   if Len>= 192 then
  218.   begin
  219.     t0:= p8x8[1,t0] xor ((K32^[2]) and $FF);
  220.     t1:= p8x8[1,t1] xor ((K32^[2] shr  8) and $FF);
  221.     t2:= p8x8[0,t2] xor ((K32^[2] shr 16) and $FF);
  222.     t3:= p8x8[0,t3] xor ((K32^[2] shr 24));
  223.   end;
  224.   Result:= MDS[0,p8x8[0,p8x8[0,t0] xor ((K32^[1]) and $FF)] xor ((K32^[0]) and $FF)] xor
  225.            MDS[1,p8x8[0,p8x8[1,t1] xor ((K32^[1] shr  8) and $FF)] xor ((K32^[0] shr  8) and $FF)] xor
  226.            MDS[2,p8x8[1,p8x8[0,t2] xor ((K32^[1] shr 16) and $FF)] xor ((K32^[0] shr 16) and $FF)] xor
  227.            MDS[3,p8x8[1,p8x8[1,t3] xor ((K32^[1] shr 24))] xor ((K32^[0] shr 24))];
  228. end;
  229.  
  230. procedure Xor256(Dst, Src: PDWordArray; v: byte);
  231. var
  232.   i, j: DWord;
  233. begin
  234.   i:= 0;
  235.   j:= v * $01010101;
  236.   while i< 64 do
  237.   begin
  238.     Dst^[i]:= Src^[i] xor j;
  239.     Dst^[i+1]:= Src^[i+1] xor j;
  240.     Dst^[i+2]:= Src^[i+2] xor j;
  241.     Dst^[i+3]:= Src^[i+3] xor j;
  242.     Inc(i,4);
  243.   end;
  244. end;
  245.  
  246. procedure TDCP_twofish.InitKey(const Key; Size: longword);
  247. const
  248.   subkeyCnt= ROUNDSUBKEYS + 2*NUMROUNDS;
  249. var
  250.   key32: array[0..7] of DWord;
  251.   k32e, k32o, sboxkeys: array[0..3] of DWord;
  252.   k64Cnt, i, j, A, B, q: DWord;
  253.   L0, L1: array[0..255] of byte;
  254. begin
  255.   FillChar(Key32,Sizeof(Key32),0);
  256.   Move(Key,Key32,Size div 8);
  257.   if Size<= 128 then           { pad the key to either 128bit, 192bit or 256bit}
  258.     Size:= 128
  259.   else if Size<= 192 then
  260.     Size:= 192
  261.   else
  262.     Size:= 256;
  263.   k64Cnt:= Size div 64;
  264.   j:= k64Cnt-1;
  265.   for i:= 0 to j do
  266.   begin
  267.     k32e[i]:= key32[2*i];
  268.     k32o[i]:= key32[2*i+1];
  269.     sboxKeys[j]:= RS_MDS_Encode(k32e[i],k32o[i]);
  270.     Dec(j);
  271.   end;
  272.   q:= 0;
  273.   for i:= 0 to ((subkeyCnt div 2)-1) do
  274.   begin
  275.     A:= f32(q,@k32e,Size);
  276.     B:= f32(q+SK_BUMP,@k32o,Size);
  277.     B:= (B shl 8) or (B shr 24);
  278.     SubKeys[2*i]:= A+B;
  279.     B:= A + 2*B;
  280.     SubKeys[2*i+1]:= (B shl SK_ROTL) or (B shr (32 - SK_ROTL)); 
  281.     Inc(q,SK_STEP);
  282.   end;
  283.   case Size of
  284.     128: begin
  285.            Xor256(@L0,@p8x8[0],(sboxKeys[1] and $FF));
  286.            A:= (sboxKeys[0] and $FF);
  287.            i:= 0;
  288.            while i< 256 do
  289.            begin
  290.              sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[0,L0[i]] xor A];
  291.              sBox[0 and 2,2*i+(0 and 1)+2]:= MDS[0,p8x8[0,L0[i+1]] xor A];
  292.              Inc(i,2);
  293.            end;
  294.            Xor256(@L0,@p8x8[1],(sboxKeys[1] shr 8) and $FF);
  295.            A:= (sboxKeys[0] shr 8) and $FF;
  296.            i:= 0;
  297.            while i< 256 do
  298.            begin
  299.              sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[0,L0[i]] xor A];
  300.              sBox[1 and 2,2*i+(1 and 1)+2]:= MDS[1,p8x8[0,L0[i+1]] xor A];
  301.              Inc(i,2);
  302.            end;
  303.            Xor256(@L0,@p8x8[0],(sboxKeys[1] shr 16) and $FF);
  304.            A:= (sboxKeys[0] shr 16) and $FF;
  305.            i:= 0;
  306.            while i< 256 do
  307.            begin
  308.              sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[1,L0[i]] xor A];
  309.              sBox[2 and 2,2*i+(2 and 1)+2]:= MDS[2,p8x8[1,L0[i+1]] xor A];
  310.              Inc(i,2);
  311.            end;
  312.            Xor256(@L0,@p8x8[1],(sboxKeys[1] shr 24));
  313.            A:= (sboxKeys[0] shr 24);
  314.            i:= 0;
  315.            while i< 256 do
  316.            begin
  317.              sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[1,L0[i]] xor A];
  318.              sBox[3 and 2,2*i+(3 and 1)+2]:= MDS[3,p8x8[1,L0[i+1]] xor A];
  319.              Inc(i,2);
  320.            end;
  321.          end;
  322.     192: begin
  323.            Xor256(@L0,@p8x8[1],sboxKeys[2] and $FF);
  324.            A:= sboxKeys[0] and $FF;
  325.            B:= sboxKeys[1] and $FF;
  326.            i:= 0;
  327.            while i< 256 do
  328.            begin
  329.              sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[0,p8x8[0,L0[i]] xor B] xor A];
  330.              sBox[0 and 2,2*i+(0 and 1)+2]:= MDS[0,p8x8[0,p8x8[0,L0[i+1]] xor B] xor A];
  331.              Inc(i,2);
  332.            end;
  333.            Xor256(@L0,@p8x8[1],(sboxKeys[2] shr 8) and $FF);
  334.            A:= (sboxKeys[0] shr 8) and $FF;
  335.            B:= (sboxKeys[1] shr 8) and $FF;
  336.            i:= 0;
  337.            while i< 256 do
  338.            begin
  339.              sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[0,p8x8[1,L0[i]] xor B] xor A];
  340.              sBox[1 and 2,2*i+(1 and 1)+2]:= MDS[1,p8x8[0,p8x8[1,L0[i+1]] xor B] xor A];
  341.              Inc(i,2);
  342.            end;
  343.            Xor256(@L0,@p8x8[0],(sboxKeys[2] shr 16) and $FF);
  344.            A:= (sboxKeys[0] shr 16) and $FF;
  345.            B:= (sboxKeys[1] shr 16) and $FF;
  346.            i:= 0;
  347.            while i< 256 do
  348.            begin
  349.              sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[1,p8x8[0,L0[i]] xor B] xor A];
  350.              sBox[2 and 2,2*i+(2 and 1)+2]:= MDS[2,p8x8[1,p8x8[0,L0[i+1]] xor B] xor A];
  351.              Inc(i,2);
  352.            end;
  353.            Xor256(@L0,@p8x8[0],(sboxKeys[2] shr 24));
  354.            A:= (sboxKeys[0] shr 24);
  355.            B:= (sboxKeys[1] shr 24);
  356.            i:= 0;
  357.            while i< 256 do
  358.            begin
  359.              sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[1,p8x8[1,L0[i]] xor B] xor A];
  360.              sBox[3 and 2,2*i+(3 and 1)+2]:= MDS[3,p8x8[1,p8x8[1,L0[i+1]] xor B] xor A];
  361.              Inc(i,2);
  362.            end;
  363.          end;
  364.     256: begin
  365.            Xor256(@L1,@p8x8[1],(sboxKeys[3]) and $FF);
  366.            i:= 0;
  367.            while i< 256 do
  368.            begin
  369.              L0[i  ]:= p8x8[1,L1[i]];
  370.              L0[i+1]:= p8x8[1,L1[i+1]];
  371.              Inc(i,2);
  372.            end;
  373.            Xor256(@L0,@L0,(sboxKeys[2]) and $FF);
  374.            A:= (sboxKeys[0]) and $FF;
  375.            B:= (sboxKeys[1]) and $FF;
  376.            i:= 0;
  377.            while i< 256 do
  378.            begin
  379.              sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[0,p8x8[0,L0[i]] xor B] xor A];
  380.              sBox[0 and 2,2*i+(0 and 1)+2]:= MDS[0,p8x8[0,p8x8[0,L0[i+1]] xor B] xor A];
  381.              Inc(i,2);
  382.            end;
  383.            Xor256(@L1,@p8x8[0],(sboxKeys[3] shr  8) and $FF);
  384.            i:= 0;
  385.            while i< 256 do
  386.            begin
  387.              L0[i  ]:= p8x8[1,L1[i]];
  388.              L0[i+1]:= p8x8[1,L1[i+1]];
  389.              Inc(i,2);
  390.            end;
  391.            Xor256(@L0,@L0,(sboxKeys[2] shr  8) and $FF);
  392.            A:= (sboxKeys[0] shr  8) and $FF;
  393.            B:= (sboxKeys[1] shr  8) and $FF;
  394.            i:= 0;
  395.            while i< 256 do
  396.            begin
  397.              sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[0,p8x8[1,L0[i]] xor B] xor A];
  398.              sBox[1 and 2,2*i+(1 and 1)+2]:= MDS[1,p8x8[0,p8x8[1,L0[i+1]] xor B] xor A];
  399.              Inc(i,2);
  400.            end;
  401.  
  402.            Xor256(@L1,@p8x8[0],(sboxKeys[3] shr 16) and $FF);
  403.            i:= 0;
  404.            while i< 256 do
  405.            begin
  406.              L0[i  ]:= p8x8[0,L1[i]];
  407.              L0[i+1]:= p8x8[0,L1[i+1]];
  408.              Inc(i,2);
  409.            end;
  410.            Xor256(@L0,@L0,(sboxKeys[2] shr 16) and $FF);
  411.            A:= (sboxKeys[0] shr 16) and $FF;
  412.            B:= (sboxKeys[1] shr 16) and $FF;
  413.            i:= 0;
  414.            while i< 256 do
  415.            begin
  416.              sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[1,p8x8[0,L0[i]] xor B] xor A];
  417.              sBox[2 and 2,2*i+(2 and 1)+2]:= MDS[2,p8x8[1,p8x8[0,L0[i+1]] xor B] xor A];
  418.              Inc(i,2);
  419.            end;
  420.            Xor256(@L1,@p8x8[1],(sboxKeys[3] shr 24));
  421.            i:= 0;
  422.            while i< 256 do
  423.            begin
  424.              L0[i  ]:= p8x8[0,L1[i]];
  425.              L0[i+1]:= p8x8[0,L1[i+1]];
  426.              Inc(i,2);
  427.            end;
  428.            Xor256(@L0,@L0,(sboxKeys[2] shr 24));
  429.            A:= (sboxKeys[0] shr 24);
  430.            B:= (sboxKeys[1] shr 24);
  431.            i:= 0;
  432.            while i< 256 do
  433.            begin
  434.              sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[1,p8x8[1,L0[i]] xor B] xor A];
  435.              sBox[3 and 2,2*i+(3 and 1)+2]:= MDS[3,p8x8[1,p8x8[1,L0[i+1]] xor B] xor A];
  436.              Inc(i,2);
  437.            end;
  438.          end;
  439.   end;
  440. end;
  441.  
  442. procedure TDCP_twofish.Burn;
  443. begin
  444.   FillChar(sBox,Sizeof(sBox),$FF);
  445.   FillChar(SubKeys,Sizeof(SubKeys),$FF);
  446.   inherited Burn;
  447. end;
  448.  
  449. procedure TDCP_twofish.EncryptECB(const InData; var OutData);
  450. var
  451.   i: longword;
  452.   t0, t1: DWord;
  453.   X: array[0..3] of DWord;
  454. begin
  455.   if not fInitialized then
  456.     raise EDCP_blockcipher.Create('Cipher not initialized');
  457.   x[0]:= PDWord(@InData)^ xor SubKeys[INPUTWHITEN];
  458.   x[1]:= PDWord(longword(@InData)+4)^ xor SubKeys[INPUTWHITEN+1];
  459.   x[2]:= PDWord(longword(@InData)+8)^ xor SubKeys[INPUTWHITEN+2];
  460.   x[3]:= PDWord(longword(@InData)+12)^ xor SubKeys[INPUTWHITEN+3];
  461.   i:= 0;
  462.   while i<= NUMROUNDS-2 do
  463.   begin
  464.     t0:= sBox[0,(x[0] shl 1) and $1fe] xor sBox[0,((x[0] shr 7) and $1fe)+1]
  465.       xor sBox[2,(x[0] shr 15) and $1fe] xor sBox[2,((x[0] shr 23) and $1fe)+1];
  466.     t1:= sBox[0,((x[1] shr 23) and $1fe)] xor sBox[0,((x[1] shl 1) and $1fe)+1]
  467.       xor sBox[2,((x[1] shr 7) and $1fe)] xor sBox[2,((x[1] shr 15) and $1fe)+1];
  468.     x[3]:= (x[3] shl 1) or (x[3] shr 31);
  469.     x[2]:= x[2] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*i]);
  470.     x[3]:= x[3] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*i+1]);
  471.     x[2]:= (x[2] shr 1) or (x[2] shl 31);
  472.  
  473.     t0:= sBox[0,(x[2] shl 1) and $1fe] xor sBox[0,((x[2] shr 7) and $1fe)+1]
  474.       xor sBox[2,((x[2] shr 15) and $1fe)] xor sBox[2,((x[2] shr 23) and $1fe)+1];
  475.     t1:= sBox[0,((x[3] shr 23) and $1fe)] xor sBox[0,((x[3] shl 1) and $1fe)+1]
  476.       xor sBox[2,((x[3] shr 7) and $1fe)] xor sBox[2,((x[3] shr 15) and $1fe)+1];
  477.     x[1]:= (x[1] shl 1) or (x[1] shr 31);
  478.     x[0]:= x[0] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)]);
  479.     x[1]:= x[1] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)+1]);
  480.     x[0]:= (x[0] shr 1) or (x[0] shl 31);
  481.     Inc(i,2);
  482.   end;
  483.   PDWord(longword(@OutData)+ 0)^:= x[2] xor SubKeys[OUTPUTWHITEN];
  484.   PDWord(longword(@OutData)+ 4)^:= x[3] xor SubKeys[OUTPUTWHITEN+1];
  485.   PDWord(longword(@OutData)+ 8)^:= x[0] xor SubKeys[OUTPUTWHITEN+2];
  486.   PDWord(longword(@OutData)+12)^:= x[1] xor SubKeys[OUTPUTWHITEN+3];
  487. end;
  488.  
  489. procedure TDCP_twofish.DecryptECB(const InData; var OutData);
  490. var
  491.   i: integer;
  492.   t0, t1: DWord;
  493.   X: array[0..3] of DWord;
  494. begin
  495.   if not fInitialized then
  496.     raise EDCP_blockcipher.Create('Cipher not initialized');
  497.   X[2]:= PDWord(@InData)^ xor SubKeys[OUTPUTWHITEN];
  498.   X[3]:= PDWord(longword(@InData)+4)^ xor SubKeys[OUTPUTWHITEN+1];
  499.   X[0]:= PDWord(longword(@InData)+8)^ xor SubKeys[OUTPUTWHITEN+2];
  500.   X[1]:= PDWord(longword(@InData)+12)^ xor SubKeys[OUTPUTWHITEN+3];
  501.   i:= NUMROUNDS-2;
  502.   while i>= 0 do
  503.   begin
  504.     t0:= sBox[0,(x[2] shl 1) and $1fe] xor sBox[0,((x[2] shr 7) and $1fe)+1]
  505.       xor sBox[2,((x[2] shr 15) and $1fe)] xor sBox[2,((x[2] shr 23) and $1fe)+1];
  506.     t1:= sBox[0,((x[3] shr 23) and $1fe)] xor sBox[0,((x[3] shl 1) and $1fe)+1]
  507.       xor sBox[2,((x[3] shr 7) and $1fe)] xor sBox[2,((x[3] shr 15) and $1fe)+1];
  508.     x[0]:= (x[0] shl 1) or (x[0] shr 31);
  509.     x[0]:= x[0] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)]);
  510.     x[1]:= x[1] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)+1]);
  511.     x[1]:= (x[1] shr 1) or (x[1] shl 31);
  512.  
  513.     t0:= sBox[0,(x[0] shl 1) and $1fe] xor sBox[0,((x[0] shr 7) and $1fe)+1]
  514.       xor sBox[2,(x[0] shr 15) and $1fe] xor sBox[2,((x[0] shr 23) and $1fe)+1];
  515.     t1:= sBox[0,((x[1] shr 23) and $1fe)] xor sBox[0,((x[1] shl 1) and $1fe)+1]
  516.       xor sBox[2,((x[1] shr 7) and $1fe)] xor sBox[2,((x[1] shr 15) and $1fe)+1];
  517.     x[2]:= (x[2] shl 1) or (x[2] shr 31);
  518.     x[2]:= x[2] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*i]);
  519.     x[3]:= x[3] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*i+1]);
  520.     x[3]:= (x[3] shr 1) or (x[3] shl 31);
  521.     Dec(i,2);
  522.   end;
  523.   PDWord(longword(@OutData)+ 0)^:= X[0] xor SubKeys[INPUTWHITEN];
  524.   PDWord(longword(@OutData)+ 4)^:= X[1] xor SubKeys[INPUTWHITEN+1];
  525.   PDWord(longword(@OutData)+ 8)^:= X[2] xor SubKeys[INPUTWHITEN+2];
  526.   PDWord(longword(@OutData)+12)^:= X[3] xor SubKeys[INPUTWHITEN+3];
  527. end;
  528.  
  529. procedure PreCompMDS;
  530. var
  531.   m1, mx, my: array[0..1] of DWord;
  532.   nI: longword;
  533. begin
  534.   for nI:= 0 to 255 do
  535.   begin
  536.     m1[0]:= p8x8[0,nI];
  537.     mx[0]:= Mul_X(m1[0]);
  538.     my[0]:= Mul_Y(m1[0]);
  539.     m1[1]:= p8x8[1,nI];
  540.     mx[1]:= Mul_X(m1[1]);
  541.     my[1]:= Mul_Y(m1[1]);
  542.     mds[0,nI]:= (m1[1] shl 0) or
  543.                 (mx[1] shl 8) or
  544.                 (my[1] shl 16) or
  545.                 (my[1] shl 24);
  546.     mds[1,nI]:= (my[0] shl 0) or
  547.                 (my[0] shl 8) or
  548.                 (mx[0] shl 16) or
  549.                 (m1[0] shl 24);
  550.     mds[2,nI]:= (mx[1] shl 0) or
  551.                 (my[1] shl 8) or
  552.                 (m1[1] shl 16) or
  553.                 (my[1] shl 24);
  554.     mds[3,nI]:= (mx[0] shl 0) or
  555.                 (m1[0] shl 8) or
  556.                 (my[0] shl 16) or
  557.                 (mx[0] shl 24);
  558.   end;
  559. end;
  560.  
  561. constructor TDCP_twofish.Create(AOwner: TComponent);
  562. begin
  563.   inherited Create(AOwner);
  564.   if not MDSDone then
  565.   begin
  566.     PreCompMDS;
  567.     MDSDone:= true;
  568.   end;
  569. end;
  570.  
  571. initialization
  572.   MDSdone:= false;
  573.  
  574. end.
  575.