DCPmisty1.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. {******************************************************************************}
  2. {* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
  3. {******************************************************************************}
  4. {* A binary compatible implementation of Misty1 *******************************}
  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 DCPmisty1;
  26. interface
  27. uses
  28. Classes, Sysutils, DCPcrypt2, DCPconst, DCPblockciphers;
  29. const
  30. NUMROUNDS= 8;
  31. type
  32. TDCP_misty1= class(TDCP_blockcipher64)
  33. protected
  34. KeyData: array[0..31] of DWord;
  35. function FI(const FI_IN, FI_KEY: DWord): DWord;
  36. function FO(const FO_IN: DWord; const k: longword): DWord;
  37. function FL(const FL_IN: DWord; const k: longword): DWord;
  38. function FLINV(const FL_IN: DWord; const k: longword): DWord;
  39. procedure InitKey(const Key; Size: longword); override;
  40. public
  41. class function GetID: integer; override;
  42. class function GetAlgorithm: string; override;
  43. class function GetMaxKeySize: integer; override;
  44. class function SelfTest: boolean; override;
  45. procedure Burn; override;
  46. procedure EncryptECB(const InData; var OutData); override;
  47. procedure DecryptECB(const InData; var OutData); override;
  48. end;
  49. {******************************************************************************}
  50. {******************************************************************************}
  51. implementation
  52. {$R-}{$Q-}
  53. {$I DCPmisty1.inc}
  54. function SwapDword(a: dword): dword;
  55. begin
  56. Result:= ((a and $FF) shl 24) or ((a and $FF00) shl 8) or ((a and $FF0000) shr 8) or ((a and $FF000000) shr 24);
  57. end;
  58. class function TDCP_misty1.GetID: integer;
  59. begin
  60. Result:= DCP_misty1;
  61. end;
  62. class function TDCP_misty1.GetAlgorithm: string;
  63. begin
  64. Result:= 'Misty1';
  65. end;
  66. class function TDCP_misty1.GetMaxKeySize: integer;
  67. begin
  68. Result:= 128;
  69. end;
  70. class function TDCP_misty1.SelfTest: boolean;
  71. const
  72. Key: array[0..15] of byte=
  73. ($00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff);
  74. Plain1: array[0..7] of byte= ($01,$23,$45,$67,$89,$ab,$cd,$ef);
  75. Plain2: array[0..7] of byte= ($fe,$dc,$ba,$98,$76,$54,$32,$10);
  76. Cipher1: array[0..7] of byte= ($8b,$1d,$a5,$f5,$6a,$b3,$d0,$7c);
  77. Cipher2: array[0..7] of byte= ($04,$b6,$82,$40,$b1,$3b,$e9,$5d);
  78. var
  79. Cipher: TDCP_misty1;
  80. Block: array[0..7] of byte;
  81. begin
  82. Cipher:= TDCP_misty1.Create(nil);
  83. Cipher.Init(Key,Sizeof(Key)*8,nil);
  84. Cipher.EncryptECB(Plain1,Block);
  85. Result:= CompareMem(@Cipher1,@Block,Sizeof(Block));
  86. Cipher.DecryptECB(Block,Block);
  87. Result:= Result and CompareMem(@Plain1,@Block,Sizeof(Block));
  88. Cipher.EncryptECB(Plain2,Block);
  89. Result:= Result and CompareMem(@Cipher2,@Block,Sizeof(Block));
  90. Cipher.DecryptECB(Block,Block);
  91. Result:= Result and CompareMem(@Plain2,@Block,Sizeof(Block));
  92. Cipher.Burn;
  93. Cipher.Free;
  94. end;
  95. function TDCP_misty1.FI(const FI_IN, FI_KEY: DWord): DWord;
  96. var
  97. d7, d9: DWord;
  98. begin
  99. d9:= (FI_IN shr 7) and $1ff;
  100. d7:= FI_IN and $7f;
  101. d9:= S9Table[d9] xor d7;
  102. d7:= (S7Table[d7] xor d9) and $7f;
  103. d7:= d7 xor ((FI_KEY shr 9) and $7f);
  104. d9:= d9 xor (FI_KEY and $1ff);
  105. d9:= S9Table[d9] xor d7;
  106. Result:= (d7 shl 9) or d9;
  107. end;
  108. function TDCP_misty1.FO(const FO_IN: DWord; const k: longword): DWord;
  109. var
  110. t0, t1: DWord;
  111. begin
  112. t0:= FO_IN shr 16;
  113. t1:= FO_IN and $FFFF;
  114. t0:= t0 xor KeyData[k];
  115. t0:= FI(t0,KeyData[((k+5) mod 8) + 8]);
  116. t0:= t0 xor t1;
  117. t1:= t1 xor KeyData[(k+2) mod 8];
  118. t1:= FI(t1,KeyData[((k+1) mod 8) + 8]);
  119. t1:= t1 xor t0;
  120. t0:= t0 xor KeyData[(k+7) mod 8];
  121. t0:= FI(t0,KeyData[((k+3) mod 8) + 8]);
  122. t0:= t0 xor t1;
  123. t1:= t1 xor KeyData[(k+4) mod 8];
  124. Result:= (t1 shl 16) or t0;
  125. end;
  126. function TDCP_misty1.FL(const FL_IN: DWord; const k: longword): DWord;
  127. var
  128. d0, d1: DWord;
  129. t: byte;
  130. begin
  131. d0:= FL_IN shr 16;
  132. d1:= FL_IN and $FFFF;
  133. if (k mod 2)<> 0 then
  134. begin
  135. t:= (k-1) div 2;
  136. d1:= d1 xor (d0 and KeyData[((t + 2) mod 8) + 8]);
  137. d0:= d0 xor (d1 or KeyData[(t + 4) mod 8]);
  138. end
  139. else
  140. begin
  141. t:= k div 2;
  142. d1:= d1 xor (d0 and KeyData[t]);
  143. d0:= d0 xor (d1 or KeyData[((t+6) mod 8) + 8]);
  144. end;
  145. Result:= (d0 shl 16) or d1;
  146. end;
  147. function TDCP_misty1.FLINV(const FL_IN: DWord; const k: longword): DWord;
  148. var
  149. d0, d1: DWord;
  150. t: byte;
  151. begin
  152. d0:= FL_IN shr 16;
  153. d1:= FL_IN and $FFFF;
  154. if (k mod 2)<> 0 then
  155. begin
  156. t:= (k-1) div 2;
  157. d0:= d0 xor (d1 or KeyData[(t+4) mod 8]);
  158. d1:= d1 xor (d0 and KeyData[((t+2) mod 8) + 8]);
  159. end
  160. else
  161. begin
  162. t:= k div 2;
  163. d0:= d0 xor (d1 or KeyData[((t+6) mod 8) + 8]);
  164. d1:= d1 xor (d0 and KeyData[t]);
  165. end;
  166. Result:= (d0 shl 16) or d1;
  167. end;
  168. procedure TDCP_misty1.InitKey(const Key; Size: longword);
  169. var
  170. KeyB: array[0..15] of byte;
  171. i: longword;
  172. begin
  173. FillChar(KeyB,Sizeof(KeyB),0);
  174. Move(Key,KeyB,Size div 8);
  175. for i:= 0 to 7 do
  176. KeyData[i]:= (KeyB[i*2] * 256) + KeyB[i*2+1];
  177. for i:= 0 to 7 do
  178. begin
  179. KeyData[i+8]:= FI(KeyData[i],KeyData[(i+1) mod 8]);
  180. KeyData[i+16]:= KeyData[i+8] and $1FF;
  181. KeyData[i+24]:= KeyData[i+8] shr 9;
  182. end;
  183. end;
  184. procedure TDCP_misty1.Burn;
  185. begin
  186. FillChar(KeyData,Sizeof(KeyData),0);
  187. inherited Burn;
  188. end;
  189. procedure TDCP_misty1.EncryptECB(const InData; var OutData);
  190. var
  191. d0, d1: DWord;
  192. i: longword;
  193. begin
  194. if not fInitialized then
  195. raise EDCP_blockcipher.Create('Cipher not initialized');
  196. d0:= SwapDWord(PDWord(@InData)^);
  197. d1:= SwapDWord(PDWord(longword(@InData)+4)^);
  198. for i:= 0 to NUMROUNDS-1 do
  199. begin
  200. if (i mod 2)= 0 then
  201. begin
  202. d0:= FL(D0,i);
  203. d1:= FL(D1,i+1);
  204. d1:= d1 xor FO(d0,i);
  205. end
  206. else
  207. d0:= d0 xor FO(d1,i);
  208. end;
  209. d0:= FL(d0,NUMROUNDS);
  210. d1:= FL(d1,NUMROUNDS+1);
  211. PDWord(@OutData)^:= SwapDWord(d1);
  212. PDWord(longword(@OutData)+4)^:= SwapDWord(d0);
  213. end;
  214. procedure TDCP_misty1.DecryptECB(const InData; var OutData);
  215. var
  216. d0, d1: DWord;
  217. i: longword;
  218. begin
  219. if not fInitialized then
  220. raise EDCP_blockcipher.Create('Cipher not initialized');
  221. d1:= SwapDWord(PDWord(@InData)^);
  222. d0:= SwapDWord(PDWord(longword(@InData)+4)^);
  223. d1:= FLINV(d1,NUMROUNDS+1);
  224. d0:= FLINV(d0,NUMROUNDS);
  225. for i:= NUMROUNDS-1 downto 0 do
  226. begin
  227. if (i mod 2)= 0 then
  228. begin
  229. d1:= d1 xor FO(d0,i);
  230. d0:= FLINV(D0,i);
  231. d1:= FLINV(D1,i+1);
  232. end
  233. else
  234. d0:= d0 xor FO(d1,i);
  235. end;
  236. PDWord(@OutData)^:= SwapDWord(d0);
  237. PDWord(longword(@OutData)+4)^:= SwapDWord(d1);
  238. end;
  239. end.