DCPcrypt2.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. {******************************************************************************}
  2. {* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
  3. {******************************************************************************}
  4. {* Main component definitions *************************************************}
  5. {******************************************************************************}
  6. {* Copyright (c) 1999-2003 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 DCPcrypt2;
  26. interface
  27. uses
  28. Classes, Sysutils, DCPconst, DCPbase64;
  29. //{$DEFINE DCP1COMPAT} { DCPcrypt v1.31 compatiblity mode - see documentation }
  30. {******************************************************************************}
  31. { A few predefined types to help out }
  32. type
  33. Pbyte= ^byte;
  34. Pword= ^word;
  35. Pdword= ^dword;
  36. Pint64= ^int64;
  37. dword= longword;
  38. Pwordarray= ^Twordarray;
  39. Twordarray= array[0..19383] of word;
  40. Pdwordarray= ^Tdwordarray;
  41. Tdwordarray= array[0..8191] of dword;
  42. {******************************************************************************}
  43. { The base class from which all hash algorithms are to be derived }
  44. type
  45. EDCP_hash= class(Exception);
  46. TDCP_hash= class(TComponent)
  47. protected
  48. fInitialized: boolean; { Whether or not the algorithm has been initialized }
  49. procedure DeadInt(Value: integer); { Knudge to display vars in the object inspector }
  50. procedure DeadStr(Value: string); { Knudge to display vars in the object inspector }
  51. private
  52. function _GetId: integer;
  53. function _GetAlgorithm: string;
  54. function _GetHashSize: integer;
  55. public
  56. property Initialized: boolean
  57. read fInitialized;
  58. class function GetId: integer; virtual;
  59. { Get the algorithm id }
  60. class function GetAlgorithm: string; virtual;
  61. { Get the algorithm name }
  62. class function GetHashSize: integer; virtual;
  63. { Get the size of the digest produced - in bits }
  64. class function SelfTest: boolean; virtual;
  65. { Tests the implementation with several test vectors }
  66. procedure Init; virtual;
  67. { Initialize the hash algorithm }
  68. procedure Final(var Digest); virtual;
  69. { Create the final digest and clear the stored information.
  70. The size of the Digest var must be at least equal to the hash size }
  71. procedure Burn; virtual;
  72. { Clear any stored information with out creating the final digest }
  73. procedure Update(const Buffer; Size: longword); virtual;
  74. { Update the hash buffer with Size bytes of data from Buffer }
  75. procedure UpdateStream(Stream: TStream; Size: longword);
  76. { Update the hash buffer with Size bytes of data from the stream }
  77. procedure UpdateStr(const Str: AnsiString);
  78. { Update the hash buffer with the string }
  79. destructor Destroy; override;
  80. published
  81. property Id: integer
  82. read _GetId write DeadInt;
  83. property Algorithm: string
  84. read _GetAlgorithm write DeadStr;
  85. property HashSize: integer
  86. read _GetHashSize write DeadInt;
  87. end;
  88. TDCP_hashclass= class of TDCP_hash;
  89. {******************************************************************************}
  90. { The base class from which all encryption components will be derived. }
  91. { Stream ciphers will be derived directly from this class where as }
  92. { Block ciphers will have a further foundation class TDCP_blockcipher. }
  93. type
  94. EDCP_cipher= class(Exception);
  95. TDCP_cipher= class(TComponent)
  96. protected
  97. fInitialized: boolean; { Whether or not the key setup has been done yet }
  98. procedure DeadInt(Value: integer); { Knudge to display vars in the object inspector }
  99. procedure DeadStr(Value: string); { Knudge to display vars in the object inspector }
  100. private
  101. function _GetId: integer;
  102. function _GetAlgorithm: string;
  103. function _GetMaxKeySize: integer;
  104. public
  105. property Initialized: boolean
  106. read fInitialized;
  107. class function GetId: integer; virtual;
  108. { Get the algorithm id }
  109. class function GetAlgorithm: string; virtual;
  110. { Get the algorithm name }
  111. class function GetMaxKeySize: integer; virtual;
  112. { Get the maximum key size (in bits) }
  113. class function SelfTest: boolean; virtual;
  114. { Tests the implementation with several test vectors }
  115. procedure Init(const Key; Size: longword; InitVector: pointer); virtual;
  116. { Do key setup based on the data in Key, size is in bits }
  117. procedure InitStr(const Key: AnsiString; HashType: TDCP_hashclass);
  118. { Do key setup based on a hash of the key string }
  119. procedure Burn; virtual;
  120. { Clear all stored key information }
  121. procedure Reset; virtual;
  122. { Reset any stored chaining information }
  123. procedure Encrypt(const Indata; var Outdata; Size: longword); virtual;
  124. { Encrypt size bytes of data and place in Outdata }
  125. procedure Decrypt(const Indata; var Outdata; Size: longword); virtual;
  126. { Decrypt size bytes of data and place in Outdata }
  127. function EncryptStream(InStream, OutStream: TStream; Size: longword): longword;
  128. { Encrypt size bytes of data from InStream and place in OutStream }
  129. function DecryptStream(InStream, OutStream: TStream; Size: longword): longword;
  130. { Decrypt size bytes of data from InStream and place in OutStream }
  131. function EncryptString(const Str: AnsiString): AnsiString; virtual;
  132. { Encrypt a string and return Base64 encoded }
  133. function DecryptString(const Str: AnsiString): AnsiString; virtual;
  134. { Decrypt a Base64 encoded string }
  135. constructor Create(AOwner: TComponent); override;
  136. destructor Destroy; override;
  137. published
  138. property Id: integer
  139. read _GetId write DeadInt;
  140. property Algorithm: string
  141. read _GetAlgorithm write DeadStr;
  142. property MaxKeySize: integer
  143. read _GetMaxKeySize write DeadInt;
  144. end;
  145. TDCP_cipherclass= class of TDCP_cipher;
  146. {******************************************************************************}
  147. { The base class from which all block ciphers are to be derived, this }
  148. { extra class takes care of the different block encryption modes. }
  149. type
  150. TDCP_ciphermode= (cmCBC, cmCFB8bit, cmCFBblock, cmOFB, cmCTR); // cmCFB8bit is equal to DCPcrypt v1.xx's CFB mode
  151. EDCP_blockcipher= class(EDCP_cipher);
  152. TDCP_blockcipher= class(TDCP_cipher)
  153. protected
  154. fCipherMode: TDCP_ciphermode; { The cipher mode the encrypt method uses }
  155. procedure InitKey(const Key; Size: longword); virtual;
  156. private
  157. function _GetBlockSize: integer;
  158. public
  159. class function GetBlockSize: integer; virtual;
  160. { Get the block size of the cipher (in bits) }
  161. procedure SetIV(const Value); virtual;
  162. { Sets the IV to Value and performs a reset }
  163. procedure GetIV(var Value); virtual;
  164. { Returns the current chaining information, not the actual IV }
  165. procedure Encrypt(const Indata; var Outdata; Size: longword); override;
  166. { Encrypt size bytes of data and place in Outdata using CipherMode }
  167. procedure Decrypt(const Indata; var Outdata; Size: longword); override;
  168. { Decrypt size bytes of data and place in Outdata using CipherMode }
  169. function EncryptString(const Str: AnsiString): AnsiString; override;
  170. { Encrypt a string and return Base64 encoded }
  171. function DecryptString(const Str: AnsiString): AnsiString; override;
  172. { Decrypt a Base64 encoded string }
  173. procedure EncryptECB(const Indata; var Outdata); virtual;
  174. { Encrypt a block of data using the ECB method of encryption }
  175. procedure DecryptECB(const Indata; var Outdata); virtual;
  176. { Decrypt a block of data using the ECB method of decryption }
  177. procedure EncryptCBC(const Indata; var Outdata; Size: longword); virtual;
  178. { Encrypt size bytes of data using the CBC method of encryption }
  179. procedure DecryptCBC(const Indata; var Outdata; Size: longword); virtual;
  180. { Decrypt size bytes of data using the CBC method of decryption }
  181. procedure EncryptCFB8bit(const Indata; var Outdata; Size: longword); virtual;
  182. { Encrypt size bytes of data using the CFB (8 bit) method of encryption }
  183. procedure DecryptCFB8bit(const Indata; var Outdata; Size: longword); virtual;
  184. { Decrypt size bytes of data using the CFB (8 bit) method of decryption }
  185. procedure EncryptCFBblock(const Indata; var Outdata; Size: longword); virtual;
  186. { Encrypt size bytes of data using the CFB (block) method of encryption }
  187. procedure DecryptCFBblock(const Indata; var Outdata; Size: longword); virtual;
  188. { Decrypt size bytes of data using the CFB (block) method of decryption }
  189. procedure EncryptOFB(const Indata; var Outdata; Size: longword); virtual;
  190. { Encrypt size bytes of data using the OFB method of encryption }
  191. procedure DecryptOFB(const Indata; var Outdata; Size: longword); virtual;
  192. { Decrypt size bytes of data using the OFB method of decryption }
  193. procedure EncryptCTR(const Indata; var Outdata; Size: longword); virtual;
  194. { Encrypt size bytes of data using the CTR method of encryption }
  195. procedure DecryptCTR(const Indata; var Outdata; Size: longword); virtual;
  196. { Decrypt size bytes of data using the CTR method of decryption }
  197. constructor Create(AOwner: TComponent); override;
  198. published
  199. property BlockSize: integer
  200. read _GetBlockSize write DeadInt;
  201. property CipherMode: TDCP_ciphermode
  202. read fCipherMode write fCipherMode default cmCBC;
  203. end;
  204. TDCP_blockcipherclass= class of TDCP_blockcipher;
  205. {******************************************************************************}
  206. { Helper functions }
  207. procedure XorBlock(var InData1, InData2; Size: longword);
  208. implementation
  209. {$Q-}{$R-}
  210. {** TDCP_hash *****************************************************************}
  211. procedure TDCP_hash.DeadInt(Value: integer);
  212. begin
  213. end;
  214. procedure TDCP_hash.DeadStr(Value: string);
  215. begin
  216. end;
  217. function TDCP_hash._GetId: integer;
  218. begin
  219. Result:= GetId;
  220. end;
  221. function TDCP_hash._GetAlgorithm: string;
  222. begin
  223. Result:= GetAlgorithm;
  224. end;
  225. function TDCP_hash._GetHashSize: integer;
  226. begin
  227. Result:= GetHashSize;
  228. end;
  229. class function TDCP_hash.GetId: integer;
  230. begin
  231. Result:= -1;
  232. end;
  233. class function TDCP_hash.GetAlgorithm: string;
  234. begin
  235. Result:= '';
  236. end;
  237. class function TDCP_hash.GetHashSize: integer;
  238. begin
  239. Result:= -1;
  240. end;
  241. class function TDCP_hash.SelfTest: boolean;
  242. begin
  243. Result:= false;
  244. end;
  245. procedure TDCP_hash.Init;
  246. begin
  247. end;
  248. procedure TDCP_hash.Final(var Digest);
  249. begin
  250. end;
  251. procedure TDCP_hash.Burn;
  252. begin
  253. end;
  254. procedure TDCP_hash.Update(const Buffer; Size: longword);
  255. begin
  256. end;
  257. procedure TDCP_hash.UpdateStream(Stream: TStream; Size: longword);
  258. var
  259. Buffer: array[0..8191] of byte;
  260. i, read: integer;
  261. begin
  262. for i:= 1 to (Size div Sizeof(Buffer)) do
  263. begin
  264. read:= Stream.Read(Buffer,Sizeof(Buffer));
  265. Update(Buffer,read);
  266. end;
  267. if (Size mod Sizeof(Buffer))<> 0 then
  268. begin
  269. read:= Stream.Read(Buffer,Size mod Sizeof(Buffer));
  270. Update(Buffer,read);
  271. end;
  272. end;
  273. procedure TDCP_hash.UpdateStr(const Str: AnsiString);
  274. begin
  275. Update(Str[1],Length(Str));
  276. end;
  277. destructor TDCP_hash.Destroy;
  278. begin
  279. if fInitialized then
  280. Burn;
  281. inherited Destroy;
  282. end;
  283. {** TDCP_cipher ***************************************************************}
  284. procedure TDCP_cipher.DeadInt(Value: integer);
  285. begin
  286. end;
  287. procedure TDCP_cipher.DeadStr(Value: string);
  288. begin
  289. end;
  290. function TDCP_cipher._GetId: integer;
  291. begin
  292. Result:= GetId;
  293. end;
  294. function TDCP_cipher._GetAlgorithm: string;
  295. begin
  296. Result:= GetAlgorithm;
  297. end;
  298. function TDCP_cipher._GetMaxKeySize: integer;
  299. begin
  300. Result:= GetMaxKeySize;
  301. end;
  302. class function TDCP_cipher.GetId: integer;
  303. begin
  304. Result:= -1;
  305. end;
  306. class function TDCP_cipher.GetAlgorithm: string;
  307. begin
  308. Result:= '';
  309. end;
  310. class function TDCP_cipher.GetMaxKeySize: integer;
  311. begin
  312. Result:= -1;
  313. end;
  314. class function TDCP_cipher.SelfTest: boolean;
  315. begin
  316. Result:= false;
  317. end;
  318. procedure TDCP_cipher.Init(const Key; Size: longword; InitVector: pointer);
  319. begin
  320. if fInitialized then
  321. Burn;
  322. if (Size <= 0) or ((Size and 3)<> 0) or (Size> longword(GetMaxKeySize)) then
  323. raise EDCP_cipher.Create('Invalid key size')
  324. else
  325. fInitialized:= true;
  326. end;
  327. procedure TDCP_cipher.InitStr(const Key: AnsiString; HashType: TDCP_hashclass);
  328. var
  329. Hash: TDCP_hash;
  330. Digest: pointer;
  331. begin
  332. if fInitialized then
  333. Burn;
  334. try
  335. GetMem(Digest,HashType.GetHashSize div 8);
  336. Hash:= HashType.Create(Self);
  337. Hash.Init;
  338. Hash.UpdateStr(Key);
  339. Hash.Final(Digest^);
  340. Hash.Free;
  341. if MaxKeySize< HashType.GetHashSize then
  342. Init(Digest^,MaxKeySize,nil)
  343. else
  344. Init(Digest^,HashType.GetHashSize,nil);
  345. FillChar(Digest^,HashType.GetHashSize div 8,$FF);
  346. FreeMem(Digest);
  347. except
  348. raise EDCP_cipher.Create('Unable to allocate sufficient memory for hash digest');
  349. end;
  350. end;
  351. procedure TDCP_cipher.Burn;
  352. begin
  353. fInitialized:= false;
  354. end;
  355. procedure TDCP_cipher.Reset;
  356. begin
  357. end;
  358. procedure TDCP_cipher.Encrypt(const Indata; var Outdata; Size: longword);
  359. begin
  360. end;
  361. procedure TDCP_cipher.Decrypt(const Indata; var Outdata; Size: longword);
  362. begin
  363. end;
  364. function TDCP_cipher.EncryptStream(InStream, OutStream: TStream; Size: longword): longword;
  365. var
  366. Buffer: array[0..8191] of byte;
  367. i, Read: longword;
  368. begin
  369. Result:= 0;
  370. for i:= 1 to (Size div Sizeof(Buffer)) do
  371. begin
  372. Read:= InStream.Read(Buffer,Sizeof(Buffer));
  373. Inc(Result,Read);
  374. Encrypt(Buffer,Buffer,Read);
  375. OutStream.Write(Buffer,Read);
  376. end;
  377. if (Size mod Sizeof(Buffer))<> 0 then
  378. begin
  379. Read:= InStream.Read(Buffer,Size mod Sizeof(Buffer));
  380. Inc(Result,Read);
  381. Encrypt(Buffer,Buffer,Read);
  382. OutStream.Write(Buffer,Read);
  383. end;
  384. end;
  385. function TDCP_cipher.DecryptStream(InStream, OutStream: TStream; Size: longword): longword;
  386. var
  387. Buffer: array[0..8191] of byte;
  388. i, Read: longword;
  389. begin
  390. Result:= 0;
  391. for i:= 1 to (Size div Sizeof(Buffer)) do
  392. begin
  393. Read:= InStream.Read(Buffer,Sizeof(Buffer));
  394. Inc(Result,Read);
  395. Decrypt(Buffer,Buffer,Read);
  396. OutStream.Write(Buffer,Read);
  397. end;
  398. if (Size mod Sizeof(Buffer))<> 0 then
  399. begin
  400. Read:= InStream.Read(Buffer,Size mod Sizeof(Buffer));
  401. Inc(Result,Read);
  402. Decrypt(Buffer,Buffer,Read);
  403. OutStream.Write(Buffer,Read);
  404. end;
  405. end;
  406. function TDCP_cipher.EncryptString(const Str: AnsiString): AnsiString;
  407. begin
  408. SetLength(Result,Length(Str));
  409. Encrypt(Str[1],Result[1],Length(Str));
  410. Result:= Base64EncodeStr(Result);
  411. end;
  412. function TDCP_cipher.DecryptString(const Str: AnsiString): AnsiString;
  413. begin
  414. Result:= Base64DecodeStr(Str);
  415. Decrypt(Result[1],Result[1],Length(Result));
  416. end;
  417. constructor TDCP_cipher.Create(AOwner: TComponent);
  418. begin
  419. inherited Create(AOwner);
  420. Burn;
  421. end;
  422. destructor TDCP_cipher.Destroy;
  423. begin
  424. if fInitialized then
  425. Burn;
  426. inherited Destroy;
  427. end;
  428. {** TDCP_blockcipher **********************************************************}
  429. procedure TDCP_blockcipher.InitKey(const Key; Size: longword);
  430. begin
  431. end;
  432. function TDCP_blockcipher._GetBlockSize: integer;
  433. begin
  434. Result:= GetBlockSize;
  435. end;
  436. class function TDCP_blockcipher.GetBlockSize: integer;
  437. begin
  438. Result:= -1;
  439. end;
  440. procedure TDCP_blockcipher.SetIV(const Value);
  441. begin
  442. end;
  443. procedure TDCP_blockcipher.GetIV(var Value);
  444. begin
  445. end;
  446. procedure TDCP_blockcipher.Encrypt(const Indata; var Outdata; Size: longword);
  447. begin
  448. case fCipherMode of
  449. cmCBC: EncryptCBC(Indata,Outdata,Size);
  450. cmCFB8bit: EncryptCFB8bit(Indata,Outdata,Size);
  451. cmCFBblock: EncryptCFBblock(Indata,Outdata,Size);
  452. cmOFB: EncryptOFB(Indata,Outdata,Size);
  453. cmCTR: EncryptCTR(Indata,Outdata,Size);
  454. end;
  455. end;
  456. function TDCP_blockcipher.EncryptString(const Str: AnsiString): AnsiString;
  457. begin
  458. SetLength(Result,Length(Str));
  459. EncryptCFB8bit(Str[1],Result[1],Length(Str));
  460. Result:= Base64EncodeStr(Result);
  461. end;
  462. function TDCP_blockcipher.DecryptString(const Str: AnsiString): AnsiString;
  463. begin
  464. Result:= Base64DecodeStr(Str);
  465. DecryptCFB8bit(Result[1],Result[1],Length(Result));
  466. end;
  467. procedure TDCP_blockcipher.Decrypt(const Indata; var Outdata; Size: longword);
  468. begin
  469. case fCipherMode of
  470. cmCBC: DecryptCBC(Indata,Outdata,Size);
  471. cmCFB8bit: DecryptCFB8bit(Indata,Outdata,Size);
  472. cmCFBblock: DecryptCFBblock(Indata,Outdata,Size);
  473. cmOFB: DecryptOFB(Indata,Outdata,Size);
  474. cmCTR: DecryptCTR(Indata,Outdata,Size);
  475. end;
  476. end;
  477. procedure TDCP_blockcipher.EncryptECB(const Indata; var Outdata);
  478. begin
  479. end;
  480. procedure TDCP_blockcipher.DecryptECB(const Indata; var Outdata);
  481. begin
  482. end;
  483. procedure TDCP_blockcipher.EncryptCBC(const Indata; var Outdata; Size: longword);
  484. begin
  485. end;
  486. procedure TDCP_blockcipher.DecryptCBC(const Indata; var Outdata; Size: longword);
  487. begin
  488. end;
  489. procedure TDCP_blockcipher.EncryptCFB8bit(const Indata; var Outdata; Size: longword);
  490. begin
  491. end;
  492. procedure TDCP_blockcipher.DecryptCFB8bit(const Indata; var Outdata; Size: longword);
  493. begin
  494. end;
  495. procedure TDCP_blockcipher.EncryptCFBblock(const Indata; var Outdata; Size: longword);
  496. begin
  497. end;
  498. procedure TDCP_blockcipher.DecryptCFBblock(const Indata; var Outdata; Size: longword);
  499. begin
  500. end;
  501. procedure TDCP_blockcipher.EncryptOFB(const Indata; var Outdata; Size: longword);
  502. begin
  503. end;
  504. procedure TDCP_blockcipher.DecryptOFB(const Indata; var Outdata; Size: longword);
  505. begin
  506. end;
  507. procedure TDCP_blockcipher.EncryptCTR(const Indata; var Outdata; Size: longword);
  508. begin
  509. end;
  510. procedure TDCP_blockcipher.DecryptCTR(const Indata; var Outdata; Size: longword);
  511. begin
  512. end;
  513. constructor TDCP_blockcipher.Create(AOwner: TComponent);
  514. begin
  515. inherited Create(AOwner);
  516. fCipherMode:= cmCBC;
  517. end;
  518. {** Helpher functions *********************************************************}
  519. procedure XorBlock(var InData1, InData2; Size: longword);
  520. var
  521. i: longword;
  522. begin
  523. for i:= 1 to Size do
  524. Pbyte(longword(@InData1)+i-1)^:= Pbyte(longword(@InData1)+i-1)^ xor Pbyte(longword(@InData2)+i-1)^;
  525. end;
  526. end.