DCPice.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. {******************************************************************************}
  2. {* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
  3. {******************************************************************************}
  4. {* A binary compatible implementation of Ice and it's variants ****************}
  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 DCPice;
  26. interface
  27. uses
  28. Classes, Sysutils, DCPcrypt2, DCPconst, DCPblockciphers;
  29. type
  30. TDCP_customice= class(TDCP_blockcipher64)
  31. protected
  32. rounds: dword;
  33. ik_keysched: array[0..31,0..2] of dword;
  34. function f(p, sk: dword): dword;
  35. procedure key_sched_build(kb: pwordarray; n: dword; keyrot: pdwordarray);
  36. procedure InitIce(const Key; Size: longword; n: dword);
  37. public
  38. procedure Burn; override;
  39. procedure EncryptECB(const InData; var OutData); override;
  40. procedure DecryptECB(const InData; var OutData); override;
  41. constructor Create(AOwner: TComponent); override;
  42. end;
  43. TDCP_ice= class(TDCP_customice)
  44. protected
  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. end;
  52. TDCP_thinice= class(TDCP_customice)
  53. protected
  54. procedure InitKey(const Key; Size: longword); override;
  55. public
  56. class function GetID: integer; override;
  57. class function GetAlgorithm: string; override;
  58. class function GetMaxKeySize: integer; override;
  59. class function SelfTest: boolean; override;
  60. end;
  61. TDCP_ice2= class(TDCP_customice)
  62. protected
  63. procedure InitKey(const Key; Size: longword); override;
  64. public
  65. class function GetID: integer; override;
  66. class function GetAlgorithm: string; override;
  67. class function GetMaxKeySize: integer; override;
  68. class function SelfTest: boolean; override;
  69. end;
  70. {******************************************************************************}
  71. {******************************************************************************}
  72. implementation
  73. {$R-}{$Q-}
  74. var
  75. ice_sbox: array[0..3,0..1023] of dword;
  76. ice_sboxdone: boolean;
  77. const
  78. ice_smod: array[0..3,0..3] of dword= (
  79. (333, 313, 505, 369),
  80. (379, 375, 319, 391),
  81. (361, 445, 451, 397),
  82. (397, 425, 395, 505));
  83. ice_sxor: array[0..3,0..3] of dword= (
  84. ($83, $85, $9b, $cd),
  85. ($cc, $a7, $ad, $41),
  86. ($4b, $2e, $d4, $33),
  87. ($ea, $cb, $2e, $04));
  88. ice_keyrot: array[0..15] of dword= (
  89. 0, 1, 2, 3, 2, 1, 3, 0,
  90. 1, 3, 2, 0, 3, 1, 0, 2);
  91. ice_pbox: array[0..31] of dword= (
  92. $00000001, $00000080, $00000400, $00002000,
  93. $00080000, $00200000, $01000000, $40000000,
  94. $00000008, $00000020, $00000100, $00004000,
  95. $00010000, $00800000, $04000000, $20000000,
  96. $00000004, $00000010, $00000200, $00008000,
  97. $00020000, $00400000, $08000000, $10000000,
  98. $00000002, $00000040, $00000800, $00001000,
  99. $00040000, $00100000, $02000000, $80000000);
  100. function SwapDword(a: dword): dword;
  101. begin
  102. Result:= ((a and $FF) shl 24) or ((a and $FF00) shl 8) or ((a and $FF0000) shr 8) or ((a and $FF000000) shr 24);
  103. end;
  104. {******************************************************************************}
  105. function gf_mult(a, b, m: dword): dword;
  106. var
  107. res: dword;
  108. begin
  109. res:= 0;
  110. while b<> 0 do
  111. begin
  112. if (b and 1)<> 0 then
  113. res:= res xor a;
  114. a:= a shl 1;
  115. b:= b shr 1;
  116. if a>= 256 then
  117. a:= a xor m;
  118. end;
  119. Result:= res;
  120. end;
  121. function gf_exp7(b, m: dword): dword;
  122. var
  123. x: dword;
  124. begin
  125. if b= 0 then
  126. Result:= 0
  127. else
  128. begin
  129. x:= gf_mult(b,b,m);
  130. x:= gf_mult(b,x,m);
  131. x:= gf_mult(x,x,m);
  132. Result:= gf_mult(b,x,m);
  133. end;
  134. end;
  135. function ice_perm32(x: dword): dword;
  136. var
  137. res: dword;
  138. pbox: pdword;
  139. begin
  140. res:= 0;
  141. pbox:= @ice_pbox;
  142. while x<> 0 do
  143. begin
  144. if (x and 1)<> 0 then
  145. res:= res or pbox^;
  146. Inc(pbox);
  147. x:= x shr 1;
  148. end;
  149. Result:= res;
  150. end;
  151. procedure ice_sboxes_init;
  152. var
  153. i, col, row: dword;
  154. x: dword;
  155. begin
  156. for i:= 0 to 1023 do
  157. begin
  158. col:= (i shr 1) and $FF;
  159. row:= (i and 1) or ((i and $200) shr 8);
  160. x:= gf_exp7(col xor ice_sxor[0,row],ice_smod[0,row]) shl 24;
  161. ice_sbox[0,i]:= ice_perm32(x);
  162. x:= gf_exp7(col xor ice_sxor[1,row],ice_smod[1,row]) shl 16;
  163. ice_sbox[1,i]:= ice_perm32(x);
  164. x:= gf_exp7(col xor ice_sxor[2,row],ice_smod[2,row]) shl 8;
  165. ice_sbox[2,i]:= ice_perm32(x);
  166. x:= gf_exp7(col xor ice_sxor[3,row],ice_smod[3,row]);
  167. ice_sbox[3,i]:= ice_perm32(x);
  168. end;
  169. end;
  170. function TDCP_customice.f(p, sk: dword): dword;
  171. var
  172. tl, tr, al, ar: dword;
  173. begin
  174. tl:= ((p shr 16) and $3ff) or (((p shr 14) or (p shl 18)) and $ffc00);
  175. tr:= (p and $3ff) or ((p shl 2) and $ffc00);
  176. al:= ik_keysched[sk,2] and (tl xor tr);
  177. ar:= al xor tr;
  178. al:= al xor tl;
  179. al:= al xor ik_keysched[sk,0];
  180. ar:= ar xor ik_keysched[sk,1];
  181. Result:= ice_sbox[0,al shr 10] or ice_sbox[1,al and $3ff] or
  182. ice_sbox[2,ar shr 10] or ice_sbox[3,ar and $3ff];
  183. end;
  184. procedure TDCP_customice.key_sched_build(kb: pwordarray; n: dword; keyrot: pdwordarray);
  185. var
  186. i, j, k, kr: dword;
  187. keys: pdwordarray;
  188. currentsk: pdword;
  189. currentkb: pword;
  190. bit: dword;
  191. begin
  192. for i:= 0 to 7 do
  193. begin
  194. kr:= keyrot^[i];
  195. keys:= @ik_keysched[n+i];
  196. for j:= 0 to 2 do
  197. keys^[j]:= 0;
  198. for j:= 0 to 14 do
  199. begin
  200. currentsk:= @keys^[j mod 3];
  201. for k:= 0 to 3 do
  202. begin
  203. currentkb:= @kb^[(kr + k) and 3];
  204. bit:= currentkb^ and 1;
  205. currentsk^:= (currentsk^ shl 1) or bit;
  206. currentkb^:= (currentkb^ shr 1) or ((bit xor 1) shl 15);
  207. end;
  208. end;
  209. end;
  210. end;
  211. procedure TDCP_customice.InitIce(const Key; Size: longword; n: dword);
  212. var
  213. i, j: dword;
  214. kb: array[0..3] of word;
  215. keyb: array[0..15] of byte;
  216. begin
  217. FillChar(keyb,Sizeof(keyb),0);
  218. Move(key,keyb,Size div 8);
  219. if n> 0 then
  220. rounds:= 16 * n
  221. else
  222. rounds:= 8;
  223. if rounds= 8 then
  224. begin
  225. for i:= 0 to 4 do
  226. kb[3 - i]:= (keyb[i*2] shl 8) or keyb[i*2 + 1];
  227. key_sched_build(@kb,0,@ice_keyrot);
  228. end
  229. else
  230. begin
  231. for i:= 0 to (n-1) do
  232. begin
  233. for j:= 0 to 3 do
  234. kb[3-j]:= (keyb[i*8 + j*2] shl 8) or keyb[i*8 + j*2 + 1];
  235. key_sched_build(@kb,i*8,@ice_keyrot);
  236. key_sched_build(@kb,rounds - 8 - i*8,@ice_keyrot[8]);
  237. end;
  238. end;
  239. end;
  240. procedure TDCP_customice.Burn;
  241. begin
  242. FillChar(ik_keysched,Sizeof(ik_keysched),0);
  243. Rounds:= 0;
  244. inherited Burn;
  245. end;
  246. procedure TDCP_customice.EncryptECB(const InData; var OutData);
  247. var
  248. i, l, r: dword;
  249. begin
  250. if not fInitialized then
  251. raise EDCP_blockcipher.Create('Cipher not initialized');
  252. l:= SwapDWord(Pdword(@InData)^);
  253. r:= SwapDWord(Pdword(longword(@InData)+4)^);
  254. i:= 0;
  255. while i< rounds do
  256. begin
  257. l:= l xor f(r,i);
  258. r:= r xor f(l,i+1);
  259. Inc(i,2);
  260. end;
  261. Pdword(@OutData)^:= SwapDWord(r);
  262. Pdword(longword(@OutData)+4)^:= SwapDWord(l);
  263. end;
  264. procedure TDCP_customice.DecryptECB(const InData; var OutData);
  265. var
  266. l, r: dword;
  267. i: integer;
  268. begin
  269. if not fInitialized then
  270. raise EDCP_blockcipher.Create('Cipher not initialized');
  271. l:= SwapDWord(Pdword(@InData)^);
  272. r:= SwapDWord(Pdword(longword(@InData)+4)^);
  273. i:= rounds-1;
  274. while i> 0 do
  275. begin
  276. l:= l xor f(r,i);
  277. r:= r xor f(l,i-1);
  278. Dec(i,2);
  279. end;
  280. Pdword(@OutData)^:= SwapDWord(r);
  281. Pdword(longword(@OutData)+4)^:= SwapDWord(l);
  282. end;
  283. constructor TDCP_customice.Create(AOwner: TComponent);
  284. begin
  285. inherited Create(AOwner);
  286. if not ice_sboxdone then
  287. begin
  288. ice_sboxes_init;
  289. ice_sboxdone:= true;
  290. end;
  291. end;
  292. {******************************************************************************}
  293. class function TDCP_ice.GetMaxKeySize: integer;
  294. begin
  295. Result:= 64;
  296. end;
  297. class function TDCP_ice.GetID: integer;
  298. begin
  299. Result:= DCP_ice;
  300. end;
  301. class function TDCP_ice.GetAlgorithm: string;
  302. begin
  303. Result:= 'Ice';
  304. end;
  305. class function TDCP_ice.SelfTest: boolean;
  306. const
  307. Key1: array[0..7] of byte= ($de,$ad,$be,$ef,$01,$23,$45,$67);
  308. InData1: array[0..7] of byte= ($fe,$dc,$ba,$98,$76,$54,$32,$10);
  309. OutData1: array[0..7] of byte= ($7d,$6e,$f1,$ef,$30,$d4,$7a,$96);
  310. var
  311. Cipher: TDCP_ice;
  312. Data: array[0..7] of byte;
  313. begin
  314. Cipher:= TDCP_ice.Create(nil);
  315. Cipher.Init(Key1,Sizeof(Key1)*8,nil);
  316. Cipher.EncryptECB(InData1,Data);
  317. Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
  318. Cipher.Reset;
  319. Cipher.DecryptECB(Data,Data);
  320. Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
  321. Cipher.Burn;
  322. Cipher.Free;
  323. end;
  324. procedure TDCP_ice.InitKey(const Key; Size: longword);
  325. begin
  326. InitIce(Key,Size,1);
  327. end;
  328. {******************************************************************************}
  329. class function TDCP_thinice.GetMaxKeySize: integer;
  330. begin
  331. Result:= 64;
  332. end;
  333. class function TDCP_thinice.GetID: integer;
  334. begin
  335. Result:= DCP_thinice;
  336. end;
  337. class function TDCP_thinice.GetAlgorithm: string;
  338. begin
  339. Result:= 'Thin Ice';
  340. end;
  341. class function TDCP_thinice.SelfTest: boolean;
  342. const
  343. Key1: array[0..7] of byte= ($de,$ad,$be,$ef,$01,$23,$45,$67);
  344. InData1: array[0..7] of byte= ($fe,$dc,$ba,$98,$76,$54,$32,$10);
  345. OutData1: array[0..7] of byte= ($de,$24,$0d,$83,$a0,$0a,$9c,$c0);
  346. var
  347. Cipher: TDCP_thinice;
  348. Data: array[0..7] of byte;
  349. begin
  350. Cipher:= TDCP_thinice.Create(nil);
  351. Cipher.Init(Key1,Sizeof(Key1)*8,nil);
  352. Cipher.EncryptECB(InData1,Data);
  353. Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
  354. Cipher.Reset;
  355. Cipher.DecryptECB(Data,Data);
  356. Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
  357. Cipher.Burn;
  358. Cipher.Free;
  359. end;
  360. procedure TDCP_thinice.InitKey(const Key; Size: longword);
  361. begin
  362. InitIce(Key,Size,0);
  363. end;
  364. {******************************************************************************}
  365. class function TDCP_ice2.GetMaxKeySize: integer;
  366. begin
  367. Result:= 128;
  368. end;
  369. class function TDCP_ice2.GetID: integer;
  370. begin
  371. Result:= DCP_ice2;
  372. end;
  373. class function TDCP_ice2.GetAlgorithm: string;
  374. begin
  375. Result:= 'Ice2';
  376. end;
  377. class function TDCP_ice2.SelfTest: boolean;
  378. const
  379. Key1: array[0..15] of byte=
  380. ($00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff);
  381. InData1: array[0..7] of byte= ($fe,$dc,$ba,$98,$76,$54,$32,$10);
  382. OutData1: array[0..7] of byte= ($f9,$48,$40,$d8,$69,$72,$f2,$1c);
  383. var
  384. Cipher: TDCP_ice2;
  385. Data: array[0..7] of byte;
  386. begin
  387. Cipher:= TDCP_ice2.Create(nil);
  388. Cipher.Init(Key1,Sizeof(Key1)*8,nil);
  389. Cipher.EncryptECB(InData1,Data);
  390. Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
  391. Cipher.Reset;
  392. Cipher.DecryptECB(Data,Data);
  393. Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
  394. Cipher.Burn;
  395. Cipher.Free;
  396. end;
  397. procedure TDCP_ice2.InitKey(const Key; Size: longword);
  398. begin
  399. InitIce(Key,Size,2);
  400. end;
  401. initialization
  402. ice_sboxdone:= false;
  403. end.