DCPidea.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. {******************************************************************************}
  2. {* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
  3. {******************************************************************************}
  4. {* A binary compatible implementation of IDEA *********************************}
  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 DCPidea;
  26. interface
  27. uses
  28. Classes, Sysutils, DCPcrypt2, DCPconst, DCPblockciphers;
  29. type
  30. TDCP_idea= class(TDCP_blockcipher64)
  31. protected
  32. EK, DK: array[0..51] of word;
  33. procedure InitKey(const Key; Size: longword); override;
  34. public
  35. class function GetID: integer; override;
  36. class function GetAlgorithm: string; override;
  37. class function GetMaxKeySize: integer; override;
  38. class function SelfTest: boolean; override;
  39. procedure Burn; override;
  40. procedure EncryptECB(const InData; var OutData); override;
  41. procedure DecryptECB(const InData; var OutData); override;
  42. end;
  43. {******************************************************************************}
  44. {******************************************************************************}
  45. implementation
  46. {$R-}{$Q-}
  47. class function TDCP_idea.GetMaxKeySize: integer;
  48. begin
  49. Result:= 128;
  50. end;
  51. class function TDCP_idea.GetID: integer;
  52. begin
  53. Result:= DCP_idea;
  54. end;
  55. class function TDCP_idea.GetAlgorithm: string;
  56. begin
  57. Result:= 'IDEA';
  58. end;
  59. class function TDCP_idea.SelfTest: boolean;
  60. const
  61. Key1: array[0..15] of byte=
  62. ($3A,$98,$4E,$20,$00,$19,$5D,$B3,$2E,$E5,$01,$C8,$C4,$7C,$EA,$60);
  63. InData1: array[0..7] of byte=
  64. ($01,$02,$03,$04,$05,$06,$07,$08);
  65. OutData1: array[0..7] of byte=
  66. ($97,$BC,$D8,$20,$07,$80,$DA,$86);
  67. Key2: array[0..15] of byte=
  68. ($00,$64,$00,$C8,$01,$2C,$01,$90,$01,$F4,$02,$58,$02,$BC,$03,$20);
  69. InData2: array[0..7] of byte=
  70. ($05,$32,$0A,$64,$14,$C8,$19,$FA);
  71. OutData2: array[0..7] of byte=
  72. ($65,$BE,$87,$E7,$A2,$53,$8A,$ED);
  73. var
  74. Cipher: TDCP_idea;
  75. Data: array[0..7] of byte;
  76. begin
  77. Cipher:= TDCP_idea.Create(nil);
  78. Cipher.Init(Key1,Sizeof(Key1)*8,nil);
  79. Cipher.EncryptECB(InData1,Data);
  80. Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
  81. Cipher.DecryptECB(Data,Data);
  82. Result:= Result and boolean(CompareMem(@Data,@InData1,Sizeof(Data)));
  83. Cipher.Burn;
  84. Cipher.Init(Key2,Sizeof(Key2)*8,nil);
  85. Cipher.EncryptECB(InData2,Data);
  86. Result:= Result and boolean(CompareMem(@Data,@OutData2,Sizeof(Data)));
  87. Cipher.DecryptECB(Data,Data);
  88. Result:= Result and boolean(CompareMem(@Data,@InData2,Sizeof(Data)));
  89. Cipher.Burn;
  90. Cipher.Free;
  91. end;
  92. function MulInv(x: word): word;
  93. var
  94. t0, t1, q, y: word;
  95. begin
  96. if x<= 1 then
  97. begin
  98. Result:= x;
  99. Exit;
  100. end;
  101. t1:= DWord($10001) div x;
  102. y:= DWord($10001) mod x;
  103. if y= 1 then
  104. begin
  105. Result:= (1 - t1) and $FFFF;
  106. Exit;
  107. end;
  108. t0:= 1;
  109. repeat
  110. q:= x div y;
  111. x:= x mod y;
  112. t0:= t0 + (q*t1);
  113. if x= 1 then
  114. begin
  115. Result:= t0;
  116. Exit;
  117. end;
  118. q:= y div x;
  119. y:= y mod x;
  120. t1:= t1 + (q*t0);
  121. until y= 1;
  122. Result:= (1-t1) and $FFFF;
  123. end;
  124. procedure TDCP_idea.InitKey(const Key; Size: longword);
  125. var
  126. i: integer;
  127. begin
  128. Size:= Size div 8;
  129. FillChar(EK,Sizeof(EK),0);
  130. Move(Key,EK,Size);
  131. for i:= 0 to 7 do
  132. EK[i]:= (EK[i] shl 8) or (EK[i] shr 8);
  133. for i:= 1 to 5 do
  134. begin
  135. EK[(i*8)+0]:= (EK[((i-1)*8)+1] shl 9) or (EK[((i-1)*8)+2] shr 7);
  136. EK[(i*8)+1]:= (EK[((i-1)*8)+2] shl 9) or (EK[((i-1)*8)+3] shr 7);
  137. EK[(i*8)+2]:= (EK[((i-1)*8)+3] shl 9) or (EK[((i-1)*8)+4] shr 7);
  138. EK[(i*8)+3]:= (EK[((i-1)*8)+4] shl 9) or (EK[((i-1)*8)+5] shr 7);
  139. EK[(i*8)+4]:= (EK[((i-1)*8)+5] shl 9) or (EK[((i-1)*8)+6] shr 7);
  140. EK[(i*8)+5]:= (EK[((i-1)*8)+6] shl 9) or (EK[((i-1)*8)+7] shr 7);
  141. EK[(i*8)+6]:= (EK[((i-1)*8)+7] shl 9) or (EK[((i-1)*8)+0] shr 7);
  142. EK[(i*8)+7]:= (EK[((i-1)*8)+0] shl 9) or (EK[((i-1)*8)+1] shr 7);
  143. end;
  144. EK[48]:= (EK[41] shl 9) or (EK[42] shr 7);
  145. EK[49]:= (EK[42] shl 9) or (EK[43] shr 7);
  146. EK[50]:= (EK[43] shl 9) or (EK[44] shr 7);
  147. EK[51]:= (EK[44] shl 9) or (EK[45] shr 7);
  148. DK[51]:= MulInv(EK[3]);
  149. DK[50]:= -EK[2];
  150. DK[49]:= -EK[1];
  151. DK[48]:= MulInv(EK[0]);
  152. for i:= 0 to 6 do
  153. begin
  154. DK[47-i*6]:= EK[i*6+5];
  155. DK[46-i*6]:= EK[i*6+4];
  156. DK[45-i*6]:= MulInv(EK[i*6+9]);
  157. DK[44-i*6]:= -EK[i*6+7];
  158. DK[43-i*6]:= -EK[i*6+8];
  159. DK[42-i*6]:= MulInv(EK[i*6+6]);
  160. end;
  161. DK[5]:= EK[47];
  162. DK[4]:= EK[46];
  163. DK[3]:= MulInv(EK[51]);
  164. DK[2]:= -EK[50];
  165. DK[1]:= -EK[49];
  166. DK[0]:= MulInv(EK[48]);
  167. end;
  168. procedure TDCP_idea.Burn;
  169. begin
  170. FillChar(EK,Sizeof(EK),0);
  171. FillChar(DK,Sizeof(DK),0);
  172. inherited Burn;
  173. end;
  174. procedure Mul(var x: word; const y: word);
  175. var
  176. p: DWord;
  177. t16: word;
  178. begin
  179. p:= DWord(x)*y;
  180. if p= 0 then
  181. x:= 1 - x - y
  182. else
  183. begin
  184. x:= p shr 16;
  185. t16:= p and $FFFF;
  186. x:= t16 - x;
  187. if (t16 < x) then
  188. Inc(x);
  189. end;
  190. end;
  191. procedure TDCP_idea.EncryptECB(const InData; var OutData);
  192. var
  193. x: array[1..4] of word;
  194. s3, s2: word;
  195. i: longword;
  196. begin
  197. if not fInitialized then
  198. raise EDCP_blockcipher.Create('Cipher not initialized');
  199. PDword(@X[1])^:= PDword(@InData)^;
  200. PDword(@X[3])^:= PDword(dword(@InData)+4)^;
  201. for i:= 1 to 4 do
  202. x[i]:= (x[i] shl 8) or (x[i] shr 8);
  203. for i:= 0 to 7 do
  204. begin
  205. Mul(x[1],EK[(i*6)+0]);
  206. Inc(x[2],EK[(i*6)+1]);
  207. Inc(x[3],EK[(i*6)+2]);
  208. Mul(x[4],EK[(i*6)+3]);
  209. s3:= x[3];
  210. x[3]:= x[3] xor x[1];
  211. Mul(x[3],EK[(i*6)+4]);
  212. s2:= x[2];
  213. x[2]:= x[2] xor x[4];
  214. Inc(x[2],x[3]);
  215. Mul(x[2],EK[(i*6)+5]);
  216. Inc(x[3],x[2]);
  217. x[1]:= x[1] xor x[2];
  218. x[4]:= x[4] xor x[3];
  219. x[2]:= x[2] xor s3;
  220. x[3]:= x[3] xor s2;
  221. end;
  222. Mul(x[1],EK[48]);
  223. Inc(x[3],EK[49]);
  224. Inc(x[2],EK[50]);
  225. Mul(x[4],EK[51]);
  226. x[1]:= (x[1] shl 8) or (x[1] shr 8);
  227. s2:= (x[3] shl 8) or (x[3] shr 8);
  228. x[3]:= (x[2] shl 8) or (x[2] shr 8);
  229. x[4]:= (x[4] shl 8) or (x[4] shr 8);
  230. x[2]:= s2;
  231. PDword(@OutData)^:= PDword(@x[1])^;
  232. PDword(dword(@OutData)+4)^:= PDword(@x[3])^;
  233. end;
  234. procedure TDCP_idea.DecryptECB(const InData; var OutData);
  235. var
  236. x: array[1..4] of word;
  237. s3, s2: word;
  238. i: longword;
  239. begin
  240. if not fInitialized then
  241. raise EDCP_blockcipher.Create('Cipher not initialized');
  242. PDword(@X[1])^:= PDword(@InData)^;
  243. PDword(@X[3])^:= PDword(dword(@InData)+4)^;
  244. for i:= 1 to 4 do
  245. x[i]:= (x[i] shl 8) or (x[i] shr 8);
  246. for i:= 0 to 7 do
  247. begin
  248. Mul(x[1],DK[(i*6)+0]);
  249. Inc(x[2],DK[(i*6)+1]);
  250. Inc(x[3],DK[(i*6)+2]);
  251. Mul(x[4],DK[(i*6)+3]);
  252. s3:= x[3];
  253. x[3]:= x[3] xor x[1];
  254. Mul(x[3],DK[(i*6)+4]);
  255. s2:= x[2];
  256. x[2]:= x[2] xor x[4];
  257. Inc(x[2],x[3]);
  258. Mul(x[2],DK[(i*6)+5]);
  259. Inc(x[3],x[2]);
  260. x[1]:= x[1] xor x[2];
  261. x[4]:= x[4] xor x[3];
  262. x[2]:= x[2] xor s3;
  263. x[3]:= x[3] xor s2;
  264. end;
  265. Mul(x[1],DK[48]);
  266. Inc(x[3],DK[49]);
  267. Inc(x[2],DK[50]);
  268. Mul(x[4],DK[51]);
  269. x[1]:= (x[1] shl 8) or (x[1] shr 8);
  270. s2:= (x[3] shl 8) or (x[3] shr 8);
  271. x[3]:= (x[2] shl 8) or (x[2] shr 8);
  272. x[4]:= (x[4] shl 8) or (x[4] shr 8);
  273. x[2]:= s2;
  274. PDword(@OutData)^:= PDword(@x[1])^;
  275. PDword(dword(@OutData)+4)^:= PDword(@x[3])^;
  276. end;
  277. end.