DCPtwofish.pas 19 KB

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