DCPblowfish.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. {******************************************************************************}
  2. {* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
  3. {******************************************************************************}
  4. {* A binary compatible implementation of Blowfish *****************************}
  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 DCPblowfish;
  26. interface
  27. uses
  28. Classes, Sysutils, DCPcrypt2, DCPconst, DCPblockciphers;
  29. type
  30. TDCP_blowfish= class(TDCP_blockcipher64)
  31. protected
  32. SBox: array[0..3,0..255] of DWord;
  33. PBox: array[0..17] of DWord;
  34. procedure InitKey(const Key; Size: longword); override;
  35. public
  36. class function GetId: integer; override;
  37. class function GetAlgorithm: string; override;
  38. class function GetMaxKeySize: integer; override;
  39. class function SelfTest: boolean; override;
  40. procedure Burn; override;
  41. procedure EncryptECB(const InData; var OutData); override;
  42. procedure DecryptECB(const InData; var OutData); override;
  43. end;
  44. {******************************************************************************}
  45. {******************************************************************************}
  46. implementation
  47. {$R-}{$Q-}
  48. {$I DCPblowfish.inc}
  49. class function TDCP_blowfish.GetID: integer;
  50. begin
  51. Result:= DCP_blowfish;
  52. end;
  53. class function TDCP_blowfish.GetAlgorithm: string;
  54. begin
  55. Result:= 'Blowfish';
  56. end;
  57. class function TDCP_blowfish.GetMaxKeySize: integer;
  58. begin
  59. Result:= 448;
  60. end;
  61. class function TDCP_blowfish.SelfTest: boolean;
  62. const
  63. Key1: array[0..7] of byte= ($00,$00,$00,$00,$00,$00,$00,$00);
  64. Key2: array[0..7] of byte= ($7C,$A1,$10,$45,$4A,$1A,$6E,$57);
  65. InData1: array[0..7] of byte= ($00,$00,$00,$00,$00,$00,$00,$00);
  66. InData2: array[0..7] of byte= ($01,$A1,$D6,$D0,$39,$77,$67,$42);
  67. OutData1: array[0..7] of byte= ($4E,$F9,$97,$45,$61,$98,$DD,$78);
  68. OutData2: array[0..7] of byte= ($59,$C6,$82,$45,$EB,$05,$28,$2B);
  69. var
  70. Cipher: TDCP_blowfish;
  71. Data: array[0..7] of byte;
  72. begin
  73. Cipher:= TDCP_blowfish.Create(nil);
  74. Cipher.Init(Key1,Sizeof(Key1)*8,nil);
  75. Cipher.EncryptECB(InData1,Data);
  76. Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
  77. Cipher.Reset;
  78. Cipher.DecryptECB(Data,Data);
  79. Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
  80. Cipher.Burn;
  81. Cipher.Init(Key2,Sizeof(Key2)*8,nil);
  82. Cipher.EncryptECB(InData2,Data);
  83. Result:= boolean(CompareMem(@Data,@OutData2,Sizeof(Data))) and Result;
  84. Cipher.Reset;
  85. Cipher.DecryptECB(Data,Data);
  86. Result:= boolean(CompareMem(@Data,@InData2,Sizeof(Data))) and Result;
  87. Cipher.Burn;
  88. Cipher.Free;
  89. end;
  90. procedure TDCP_blowfish.InitKey(const Key; Size: longword);
  91. var
  92. i, k: longword;
  93. A: DWord;
  94. KeyB: PByteArray;
  95. Block: array[0..7] of byte;
  96. begin
  97. Size:= Size div 8;
  98. KeyB:= @Key;
  99. Move(SBoxOrg,SBox,Sizeof(SBox));
  100. Move(PBoxOrg,PBox,Sizeof(PBox));
  101. k:= 0;
  102. for i:= 0 to 17 do
  103. begin
  104. A:= dword(KeyB^[(k+3) mod Size]);
  105. A:= A + (dword(KeyB^[(k+2) mod Size]) shl 8);
  106. A:= A + (dword(KeyB^[(k+1) mod Size]) shl 16);
  107. A:= A + (dword(KeyB^[k]) shl 24);
  108. PBox[i]:= PBox[i] xor A;
  109. k:= (k+4) mod Size;
  110. end;
  111. FillChar(Block,Sizeof(Block),0);
  112. for i:= 0 to 8 do
  113. begin
  114. EncryptECB(Block,Block);
  115. PBox[i*2]:= dword(Block[3]) + (dword(Block[2]) shl 8) + (dword(Block[1]) shl 16) + (dword(Block[0]) shl 24);
  116. PBox[i*2+1]:= dword(Block[7]) + (dword(Block[6]) shl 8) + (dword(Block[5]) shl 16) + (dword(Block[4]) shl 24);
  117. end;
  118. for k:= 0 to 3 do
  119. begin
  120. for i:= 0 to 127 do
  121. begin
  122. EncryptECB(Block,Block);
  123. SBox[k,i*2]:= dword(Block[3]) + (dword(Block[2]) shl 8) + (dword(Block[1]) shl 16) + (dword(Block[0]) shl 24);
  124. SBox[k,i*2+1]:= dword(Block[7]) + (dword(Block[6]) shl 8) + (dword(Block[5]) shl 16) + (dword(Block[4]) shl 24);
  125. end;
  126. end;
  127. end;
  128. procedure TDCP_blowfish.Burn;
  129. begin
  130. FillChar(SBox,Sizeof(SBox),$FF);
  131. FillChar(PBox,Sizeof(PBox),$FF);
  132. inherited Burn;
  133. end;
  134. procedure TDCP_blowfish.EncryptECB(const InData; var OutData);
  135. var
  136. xL, xR: DWord;
  137. begin
  138. if not fInitialized then
  139. raise EDCP_blockcipher.Create('Cipher not initialized');
  140. xL:= Pdword(@InData)^;
  141. xR:= Pdword(longword(@InData)+4)^;
  142. xL:= ((xL and $FF) shl 24) or ((xL and $FF00) shl 8) or ((xL and $FF0000) shr 8) or ((xL and $FF000000) shr 24);
  143. xR:= ((xR and $FF) shl 24) or ((xR and $FF00) shl 8) or ((xR and $FF0000) shr 8) or ((xR and $FF000000) shr 24);
  144. xL:= xL xor PBox[0];
  145. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  146. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[1];
  147. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  148. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[2];
  149. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  150. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[3];
  151. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  152. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[4];
  153. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  154. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[5];
  155. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  156. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[6];
  157. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  158. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[7];
  159. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  160. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[8];
  161. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  162. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[9];
  163. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  164. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[10];
  165. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  166. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[11];
  167. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  168. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[12];
  169. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  170. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[13];
  171. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  172. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[14];
  173. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  174. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[15];
  175. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  176. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[16];
  177. xR:= xR xor PBox[17];
  178. xL:= ((xL and $FF) shl 24) or ((xL and $FF00) shl 8) or ((xL and $FF0000) shr 8) or ((xL and $FF000000) shr 24);
  179. xR:= ((xR and $FF) shl 24) or ((xR and $FF00) shl 8) or ((xR and $FF0000) shr 8) or ((xR and $FF000000) shr 24);
  180. Pdword(@OutData)^:= xR;
  181. Pdword(longword(@OutData)+4)^:= xL;
  182. end;
  183. procedure TDCP_blowfish.DecryptECB(const InData; var OutData);
  184. var
  185. xL, xR: DWord;
  186. begin
  187. if not fInitialized then
  188. raise EDCP_blockcipher.Create('Cipher not initialized');
  189. xL:= Pdword(@InData)^;
  190. xR:= Pdword(longword(@InData)+4)^;
  191. xL:= (xL shr 24) or ((xL shr 8) and $FF00) or ((xL shl 8) and $FF0000) or (xL shl 24);
  192. xR:= (xR shr 24) or ((xR shr 8) and $FF00) or ((xR shl 8) and $FF0000) or (xR shl 24);
  193. xL:= xL xor PBox[17];
  194. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  195. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[16];
  196. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  197. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[15];
  198. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  199. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[14];
  200. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  201. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[13];
  202. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  203. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[12];
  204. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  205. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[11];
  206. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  207. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[10];
  208. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  209. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[9];
  210. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  211. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[8];
  212. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  213. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[7];
  214. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  215. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[6];
  216. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  217. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[5];
  218. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  219. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[4];
  220. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  221. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[3];
  222. xR:= xR xor (((SBox[0,(xL shr 24) and $FF] + SBox[1,(xL shr 16) and $FF]) xor
  223. SBox[2,(xL shr 8) and $FF]) + SBox[3,xL and $FF]) xor PBox[2];
  224. xL:= xL xor (((SBox[0,(xR shr 24) and $FF] + SBox[1,(xR shr 16) and $FF]) xor
  225. SBox[2,(xR shr 8) and $FF]) + SBox[3,xR and $FF]) xor PBox[1];
  226. xR:= xR xor PBox[0];
  227. xL:= (xL shr 24) or ((xL shr 8) and $FF00) or ((xL shl 8) and $FF0000) or (xL shl 24);
  228. xR:= (xR shr 24) or ((xR shr 8) and $FF00) or ((xR shl 8) and $FF0000) or (xR shl 24);
  229. Pdword(@OutData)^:= xR;
  230. Pdword(longword(@OutData)+4)^:= xL;
  231. end;
  232. end.