Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | daniel-mar | 1 | {Copyright: Hagen Reddmann HaReddmann at T-Online dot de |
2 | Author: Hagen Reddmann |
||
3 | Remarks: freeware, but this Copyright must be included |
||
4 | known Problems: none |
||
5 | Version: 5.1, Part I from Delphi Encryption Compendium ( DEC Part I) |
||
6 | Delphi 5 |
||
7 | |||
8 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS |
||
9 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
10 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
11 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE |
||
12 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
13 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
14 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
||
15 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||
16 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
||
17 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
||
18 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
19 | } |
||
20 | |||
21 | unit DECCipher; |
||
22 | |||
23 | interface |
||
24 | |||
25 | uses SysUtils, Classes, DECUtil, DECFmt; |
||
26 | |||
27 | {$I VER.INC} |
||
28 | |||
29 | type |
||
30 | TCipher_Null = class; // Null cipher, does'nt encrypt, copying only |
||
31 | TCipher_Blowfish = class; |
||
32 | TCipher_Twofish = class; {AES Round 2 Final Candidate} |
||
33 | TCipher_IDEA = class; |
||
34 | TCipher_Cast256 = class; |
||
35 | TCipher_Mars = class; {AES Round 2 Final Candidate} |
||
36 | TCipher_RC4 = class; {Streamcipher in as Block Cipher} |
||
37 | TCipher_RC6 = class; {AES Round 2 Final Candidate} |
||
38 | TCipher_Rijndael = class; {AES Round 2 Final Candidate} |
||
39 | TCipher_Square = class; |
||
40 | TCipher_SCOP = class; {Streamcipher on Longword, very fast} |
||
41 | TCipher_Sapphire = class; {Stream Cipher, eq. Design from german ENIGMA Machine} |
||
42 | TCipher_1DES = class; {Single DES 8 byte Blocksize, 8 byte Keysize 56 bits relevant} |
||
43 | TCipher_2DES = class; {Triple DES 8 byte Blocksize, 16 byte Keysize 112 bits relevant} |
||
44 | TCipher_3DES = class; {Triple DES 8 byte Blocksize, 24 byte Keysize 168 bits relevant} |
||
45 | TCipher_2DDES = class; {Triple DES 16 byte Blocksize, 16 byte Keysize 112 bits relevant} |
||
46 | TCipher_3DDES = class; {Triple DES 16 byte Blocksize, 24 byte Keysize 168 bits relevant} |
||
47 | TCipher_3TDES = class; {Triple DES 24 byte Blocksize, 24 byte Keysize 168 bits relevant} |
||
48 | TCipher_3Way = class; |
||
49 | TCipher_Cast128 = class; |
||
50 | TCipher_Gost = class; |
||
51 | TCipher_Misty = class; |
||
52 | TCipher_NewDES = class; |
||
53 | TCipher_Q128 = class; |
||
54 | TCipher_RC2 = class; |
||
55 | TCipher_RC5 = class; |
||
56 | TCipher_SAFER = class; |
||
57 | TCipher_Shark = class; |
||
58 | TCipher_Skipjack = class; |
||
59 | TCipher_TEA = class; |
||
60 | TCipher_TEAN = class; |
||
61 | |||
62 | TCipherContext = packed record |
||
63 | KeySize: Integer; // maximal key size in bytes |
||
64 | BlockSize: Integer; // mininmal block size in bytes, eg. 1 = Streamcipher |
||
65 | BufferSize: Integer; // internal buffersize in bytes |
||
66 | UserSize: Integer; // internal size in bytes of cipher dependend structures |
||
67 | UserSave: Boolean; |
||
68 | end; |
||
69 | |||
70 | TCipherState = (csNew, csInitialized, csEncode, csDecode, csPadded, csDone); |
||
71 | TCipherStates = set of TCipherState; |
||
72 | { TCipher.State represents the internal state of processing |
||
73 | csNew = cipher isn't initialized, .Init() must be called before en/decode |
||
74 | csInitialized = cipher is initialized by .Init(), eg. Keysetup was processed |
||
75 | csEncode = Encodeing was started, and more chunks can be encoded, but not decoded |
||
76 | csDecode = Decodeing was started, and more chunks can be decoded, but not encoded |
||
77 | csPadded = trough En/Decodeing the messagechunks are padded, no more chunks can |
||
78 | be processed, the cipher is blocked. |
||
79 | csDone = Processing is finished and Cipher.Done was called. Now new En/Decoding |
||
80 | can be started without calling .Init() before. csDone is basicaly |
||
81 | identical to csInitialized, except Cipher.Buffer holds the encrypted |
||
82 | last state of Cipher.Feedback, thus Cipher.Buffer can be used as C-MAC.} |
||
83 | |||
84 | TCipherMode = (cmCTSx, cmCBCx, cmCFB8, cmCFBx, cmOFB8, cmOFBx, cmCFS8, cmCFSx, cmECBx); |
||
85 | { cmCTSx = double CBC, with CFS8 padding of truncated final block |
||
86 | cmCBCx = Cipher Block Chainung, with CFB8 padding of truncated final block |
||
87 | cmCFB8 = 8bit Cipher Feedback mode |
||
88 | cmCFBx = CFB on Blocksize of Cipher |
||
89 | cmOFB8 = 8bit Output Feedback mode |
||
90 | cmOFBx = OFB on Blocksize bytes |
||
91 | cmCFS8 = 8Bit CFS, double CFB |
||
92 | cmCFSx = CFS on Blocksize bytes |
||
93 | cmECBx = Electronic Code Book |
||
94 | |||
95 | Modes cmCBCx, cmCTSx, cmCFBx, cmOFBx, cmCFSx, cmECBx working on Blocks of |
||
96 | Cipher.BufferSize bytes, on Blockcipher that's equal to Cipher.BlockSize. |
||
97 | |||
98 | Modes cmCFB8, cmOFB8, cmCFS8 work on 8 bit Feedback Shift Registers. |
||
99 | |||
100 | Modes cmCTSx, cmCFSx, cmCFS8 are prohibitary modes developed by me. These modes |
||
101 | works such as cmCBCx, cmCFBx, cmCFB8 but with double XOR'ing of the inputstream |
||
102 | into Feedback register. |
||
103 | |||
104 | Mode cmECBx need message padding to a multiple of Cipher.BlockSize and should |
||
105 | be only used in 1byte Streamciphers. |
||
106 | |||
107 | Modes cmCTSx, cmCBCx need no external padding, because internal the last truncated |
||
108 | block is padded by cmCFS8 or cmCFB8. After padding these Mode can't be used to |
||
109 | process more data. If it needed to process chunks of data then each chunk must |
||
110 | be algined to Cipher.BufferSize bytes. |
||
111 | |||
112 | Modes cmCFBx,cmCFB8,cmOFBx,cmOFB8,cmCFSx,cmCFS8 need no padding. |
||
113 | |||
114 | } |
||
115 | TDECCipherCodeEvent = procedure(const Source; var Dest; DataSize: Integer) of object; |
||
116 | |||
117 | TDECCipherClass = class of TDECCipher; |
||
118 | |||
119 | TDECCipher = class(TDECObject) |
||
120 | private |
||
121 | FState: TCipherState; |
||
122 | FMode: TCipherMode; |
||
123 | FData: PByteArray; |
||
124 | FDataSize: Integer; |
||
125 | procedure SetMode(Value: TCipherMode); |
||
126 | protected |
||
127 | FBufferSize: Integer; |
||
128 | FBufferIndex: Integer; |
||
129 | FUserSize: Integer; |
||
130 | FBuffer: PByteArray; |
||
131 | FVector: PByteArray; |
||
132 | FFeedback: PByteArray; |
||
133 | FUser: Pointer; |
||
134 | FUserSave: Pointer; |
||
135 | procedure CheckState(States: TCipherStates); |
||
136 | procedure DoInit(const Key; Size: Integer); virtual; abstract; |
||
137 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); virtual; abstract; |
||
138 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); virtual; abstract; |
||
139 | public |
||
140 | constructor Create; override; |
||
141 | destructor Destroy; override; |
||
142 | |||
143 | class function Context: TCipherContext; virtual; abstract; |
||
144 | |||
145 | procedure Init(const Key; Size: Integer; const IVector; IVectorSize: Integer; IFiller: Byte = $FF); overload; |
||
146 | procedure Init(const Key: Binary; const IVector: Binary = ''; IFiller: Byte = $FF); overload; |
||
147 | procedure Done; |
||
148 | procedure Protect; virtual; |
||
149 | |||
150 | procedure Encode(const Source; var Dest; DataSize: Integer); |
||
151 | procedure Decode(const Source; var Dest; DataSize: Integer); |
||
152 | |||
153 | function EncodeBinary(const Source: Binary; Format: TDECFormatClass = nil): Binary; |
||
154 | function DecodeBinary(const Source: Binary; Format: TDECFormatClass = nil): Binary; |
||
155 | procedure EncodeFile(const Source, Dest: String; const Progress: IDECProgress = nil); |
||
156 | procedure DecodeFile(const Source, Dest: String; const Progress: IDECProgress = nil); |
||
157 | procedure EncodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress = nil); |
||
158 | procedure DecodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress = nil); |
||
159 | |||
160 | function CalcMAC(Format: TDECFormatClass = nil): Binary; |
||
161 | |||
162 | property InitVectorSize: Integer read FBufferSize; |
||
163 | property InitVector: PByteArray read FVector; // buffer size bytes |
||
164 | property Feedback: PByteArray read FFeedback; // buffer size bytes |
||
165 | |||
166 | property State: TCipherState read FState; |
||
167 | published |
||
168 | property Mode: TCipherMode read FMode write SetMode; |
||
169 | end; |
||
170 | |||
171 | TCipher_Null = class(TDECCipher) |
||
172 | protected |
||
173 | procedure DoInit(const Key; Size: Integer); override; |
||
174 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
175 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
176 | public |
||
177 | class function Context: TCipherContext; override; |
||
178 | end; |
||
179 | |||
180 | TCipher_Blowfish = class(TDECCipher) |
||
181 | protected |
||
182 | procedure DoInit(const Key; Size: Integer); override; |
||
183 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
184 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
185 | public |
||
186 | class function Context: TCipherContext; override; |
||
187 | end; |
||
188 | |||
189 | TCipher_Twofish = class(TDECCipher) |
||
190 | protected |
||
191 | procedure DoInit(const Key; Size: Integer); override; |
||
192 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
193 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
194 | public |
||
195 | class function Context: TCipherContext; override; |
||
196 | end; |
||
197 | |||
198 | TCipher_IDEA = class(TDECCipher) {International Data Encryption Algorithm } |
||
199 | protected |
||
200 | procedure DoInit(const Key; Size: Integer); override; |
||
201 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
202 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
203 | public |
||
204 | class function Context: TCipherContext; override; |
||
205 | end; |
||
206 | |||
207 | TCipher_Cast256 = class(TDECCipher) |
||
208 | protected |
||
209 | procedure DoInit(const Key; Size: Integer); override; |
||
210 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
211 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
212 | public |
||
213 | class function Context: TCipherContext; override; |
||
214 | end; |
||
215 | |||
216 | TCipher_Mars = class(TDECCipher) |
||
217 | protected |
||
218 | procedure DoInit(const Key; Size: Integer); override; |
||
219 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
220 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
221 | public |
||
222 | class function Context: TCipherContext; override; |
||
223 | end; |
||
224 | |||
225 | TCipher_RC4 = class(TDECCipher) |
||
226 | protected |
||
227 | procedure DoInit(const Key; Size: Integer); override; |
||
228 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
229 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
230 | public |
||
231 | class function Context: TCipherContext; override; |
||
232 | end; |
||
233 | |||
234 | TCipher_RC6 = class(TDECCipher) |
||
235 | private |
||
236 | FRounds: Integer; {16-24, default 20} |
||
237 | procedure SetRounds(Value: Integer); |
||
238 | protected |
||
239 | procedure DoInit(const Key; Size: Integer); override; |
||
240 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
241 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
242 | public |
||
243 | class function Context: TCipherContext; override; |
||
244 | published |
||
245 | property Rounds: Integer read FRounds write SetRounds; |
||
246 | end; |
||
247 | |||
248 | TCipher_Rijndael = class(TDECCipher) |
||
249 | private |
||
250 | FRounds: Integer; |
||
251 | protected |
||
252 | procedure DoInit(const Key; Size: Integer); override; |
||
253 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
254 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
255 | public |
||
256 | class function Context: TCipherContext; override; |
||
257 | published |
||
258 | property Rounds: Integer read FRounds; |
||
259 | end; |
||
260 | |||
261 | TCipher_Square = class(TDECCipher) |
||
262 | protected |
||
263 | procedure DoInit(const Key; Size: Integer); override; |
||
264 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
265 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
266 | public |
||
267 | class function Context: TCipherContext; override; |
||
268 | end; |
||
269 | |||
270 | TCipher_SCOP = class(TDECCipher) {Stream Cipher in Blockmode} |
||
271 | protected |
||
272 | procedure DoInit(const Key; Size: Integer); override; |
||
273 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
274 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
275 | public |
||
276 | class function Context: TCipherContext; override; |
||
277 | end; |
||
278 | |||
279 | TCipher_Sapphire = class(TDECCipher) |
||
280 | protected |
||
281 | procedure DoInit(const Key; Size: Integer); override; |
||
282 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
283 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
284 | public |
||
285 | class function Context: TCipherContext; override; |
||
286 | end; |
||
287 | |||
288 | TCipher_1DES = class(TDECCipher) |
||
289 | protected |
||
290 | procedure DoInitKey(const Data: array of Byte; Key: PLongArray; Reverse: Boolean); |
||
291 | procedure DoInit(const Key; Size: Integer); override; |
||
292 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
293 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
294 | public |
||
295 | class function Context: TCipherContext; override; |
||
296 | end; |
||
297 | |||
298 | TCipher_2DES = class(TCipher_1DES) |
||
299 | protected |
||
300 | procedure DoInit(const Key; Size: Integer); override; |
||
301 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
302 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
303 | public |
||
304 | class function Context: TCipherContext; override; |
||
305 | end; |
||
306 | |||
307 | TCipher_3DES = class(TCipher_1DES) |
||
308 | protected |
||
309 | procedure DoInit(const Key; Size: Integer); override; |
||
310 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
311 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
312 | public |
||
313 | class function Context: TCipherContext; override; |
||
314 | end; |
||
315 | |||
316 | TCipher_2DDES = class(TCipher_2DES) |
||
317 | protected |
||
318 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
319 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
320 | public |
||
321 | class function Context: TCipherContext; override; |
||
322 | end; |
||
323 | |||
324 | TCipher_3DDES = class(TCipher_3DES) |
||
325 | protected |
||
326 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
327 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
328 | public |
||
329 | class function Context: TCipherContext; override; |
||
330 | end; |
||
331 | |||
332 | TCipher_3TDES = class(TCipher_3DES) |
||
333 | protected |
||
334 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
335 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
336 | public |
||
337 | class function Context: TCipherContext; override; |
||
338 | end; |
||
339 | |||
340 | TCipher_3Way = class(TDECCipher) |
||
341 | protected |
||
342 | procedure DoInit(const Key; Size: Integer); override; |
||
343 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
344 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
345 | public |
||
346 | class function Context: TCipherContext; override; |
||
347 | end; |
||
348 | |||
349 | TCipher_Cast128 = class(TDECCipher) {Carlisle Adams and Stafford Tavares } |
||
350 | private |
||
351 | FRounds: Integer; |
||
352 | procedure SetRounds(Value: Integer); |
||
353 | protected |
||
354 | procedure DoInit(const Key; Size: Integer); override; |
||
355 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
356 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
357 | public |
||
358 | class function Context: TCipherContext; override; |
||
359 | published |
||
360 | property Rounds: Integer read FRounds write SetRounds; |
||
361 | end; |
||
362 | |||
363 | TCipher_Gost = class(TDECCipher) {russian Cipher} |
||
364 | protected |
||
365 | procedure DoInit(const Key; Size: Integer); override; |
||
366 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
367 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
368 | public |
||
369 | class function Context: TCipherContext; override; |
||
370 | end; |
||
371 | |||
372 | TCipher_Misty = class(TDECCipher) |
||
373 | protected |
||
374 | procedure DoInit(const Key; Size: Integer); override; |
||
375 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
376 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
377 | public |
||
378 | class function Context: TCipherContext; override; |
||
379 | end; |
||
380 | |||
381 | { This algorithm resembles the Data Encryption Standard (DES), but is easier |
||
382 | to implement in software and is supposed to be more secure. |
||
383 | It is not to be confused with another algorithm--known by the |
||
384 | same name--which is simply DES without the initial and final |
||
385 | permutations. The NewDES here is a completely different algorithm.} |
||
386 | |||
387 | TCipher_NewDES = class(TDECCipher) |
||
388 | protected |
||
389 | procedure DoInit(const Key; Size: Integer); override; |
||
390 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
391 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
392 | public |
||
393 | class function Context: TCipherContext; override; |
||
394 | end; |
||
395 | |||
396 | TCipher_Q128 = class(TDECCipher) |
||
397 | protected |
||
398 | procedure DoInit(const Key; Size: Integer); override; |
||
399 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
400 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
401 | public |
||
402 | class function Context: TCipherContext; override; |
||
403 | end; |
||
404 | |||
405 | TCipher_RC2 = class(TDECCipher) |
||
406 | protected |
||
407 | procedure DoInit(const Key; Size: Integer); override; |
||
408 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
409 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
410 | public |
||
411 | class function Context: TCipherContext; override; |
||
412 | end; |
||
413 | |||
414 | TCipher_RC5 = class(TDECCipher) |
||
415 | private |
||
416 | FRounds: Integer; {8-16, default 12} |
||
417 | procedure SetRounds(Value: Integer); |
||
418 | protected |
||
419 | procedure DoInit(const Key; Size: Integer); override; |
||
420 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
421 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
422 | public |
||
423 | class function Context: TCipherContext; override; |
||
424 | published |
||
425 | property Rounds: Integer read FRounds write SetRounds; |
||
426 | end; |
||
427 | |||
428 | TSAFERVersion = (svSK128, svSK64, svSK40, svK128, svK64, svK40); |
||
429 | {svK40 SAFER K-40 Keysize is 40bit -> 5 Byte |
||
430 | svK64 SAFER K-64 Keysize is 64bit -> 8 Byte |
||
431 | svK128 SAFER K-128 KeySize is 128bit -> 16 Byte |
||
432 | svSK40 SAFER SK-40 stronger Version from K-40 with better Keyscheduling |
||
433 | svSK64 SAFER SK-64 stronger Version from K-64 with better Keyscheduling |
||
434 | svSK128 SAFER SK-128 stronger Version from K-128 with better Keyscheduling} |
||
435 | |||
436 | TCipher_SAFER = class(TDECCipher) {SAFER = Secure And Fast Encryption Routine} |
||
437 | private |
||
438 | FRounds: Integer; |
||
439 | FVersion: TSAFERVersion; |
||
440 | procedure SetRounds(Value: Integer); |
||
441 | procedure SetVersion(Value: TSAFERVersion); |
||
442 | protected |
||
443 | procedure DoInit(const Key; Size: Integer); override; |
||
444 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
445 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
446 | public |
||
447 | class function Context: TCipherContext; override; |
||
448 | published |
||
449 | property Rounds: Integer read FRounds write SetRounds; |
||
450 | property Version: TSAFERVersion read FVersion write SetVersion; |
||
451 | end; |
||
452 | |||
453 | TCipher_Shark = class(TDECCipher) |
||
454 | protected |
||
455 | procedure DoInit(const Key; Size: Integer); override; |
||
456 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
457 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
458 | public |
||
459 | class function Context: TCipherContext; override; |
||
460 | end; |
||
461 | |||
462 | TCipher_Skipjack = class(TDECCipher) |
||
463 | protected |
||
464 | procedure DoInit(const Key; Size: Integer); override; |
||
465 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
466 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
467 | public |
||
468 | class function Context: TCipherContext; override; |
||
469 | end; |
||
470 | |||
471 | TCipher_TEA = class(TDECCipher) {Tiny Encryption Algorithm} |
||
472 | private |
||
473 | FRounds: Integer; {16 - 32, default 16 is sufficient, 32 is ample} |
||
474 | procedure SetRounds(Value: Integer); |
||
475 | protected |
||
476 | procedure DoInit(const Key; Size: Integer); override; |
||
477 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
478 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
479 | public |
||
480 | class function Context: TCipherContext; override; |
||
481 | published |
||
482 | property Rounds: Integer read FRounds write SetRounds; |
||
483 | end; |
||
484 | |||
485 | TCipher_TEAN = class(TCipher_TEA) {Tiny Encryption Algorithm, extended Version} |
||
486 | protected |
||
487 | procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; |
||
488 | procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; |
||
489 | end; |
||
490 | |||
491 | function ValidCipher(CipherClass: TDECCipherClass = nil): TDECCipherClass; |
||
492 | function CipherByName(const Name: String): TDECCipherClass; |
||
493 | function CipherByIdentity(Identity: LongWord): TDECCipherClass; |
||
494 | procedure SetDefaultCipherClass(CipherClass: TDECCipherClass = nil); |
||
495 | |||
496 | var |
||
497 | StreamBufferSize: Integer = 8192; |
||
498 | |||
499 | implementation |
||
500 | |||
501 | uses TypInfo, DECData; |
||
502 | |||
503 | resourcestring |
||
504 | sAlreadyPadded = 'Cipher have already padded, can not process message'; |
||
505 | sInvalidState = 'Cipher is not in valid state for this action'; |
||
506 | sInvalidMessageLength = 'Messagelength for %s must be a multiple of %d bytes'; |
||
507 | sKeyMaterialToLarge = 'Keymaterial is to large as can be used, security issue'; |
||
508 | sIVMaterialToLarge = 'Initvector is to large as can be used, security issue'; |
||
509 | sInvalidMACMode = 'Invalid Cipher mode to compute MAC'; |
||
510 | sCipherNoDefault = 'No default cipher are registered'; |
||
511 | |||
512 | var |
||
513 | FDefaultCipherClass: TDECCipherClass = nil; |
||
514 | |||
515 | function ValidCipher(CipherClass: TDECCipherClass): TDECCipherClass; |
||
516 | begin |
||
517 | if CipherClass <> nil then Result := CipherClass |
||
518 | else Result := FDefaultCipherClass; |
||
519 | if Result = nil then raise EDECException.Create(sCipherNoDefault); |
||
520 | end; |
||
521 | |||
522 | function CipherByName(const Name: String): TDECCipherClass; |
||
523 | begin |
||
524 | Result := TDECCipherClass(DECClassByName(Name, TDECCipher)); |
||
525 | end; |
||
526 | |||
527 | function CipherByIdentity(Identity: LongWord): TDECCipherClass; |
||
528 | begin |
||
529 | Result := TDECCipherClass(DECClassByIdentity(Identity, TDECCipher)); |
||
530 | end; |
||
531 | |||
532 | procedure SetDefaultCipherClass(CipherClass: TDECCipherClass); |
||
533 | begin |
||
534 | if CipherClass <> nil then CipherClass.Register; |
||
535 | FDefaultCipherClass := CipherClass; |
||
536 | end; |
||
537 | |||
538 | procedure TDECCipher.SetMode(Value: TCipherMode); |
||
539 | begin |
||
540 | if Value <> FMode then |
||
541 | begin |
||
542 | if not (FState in [csNew, csInitialized, csDone]) then Done; |
||
543 | FMode := Value; |
||
544 | end; |
||
545 | end; |
||
546 | |||
547 | procedure TDECCipher.CheckState(States: TCipherStates); |
||
548 | var |
||
549 | S: String; |
||
550 | begin |
||
551 | if not (FState in States) then |
||
552 | begin |
||
553 | if FState = csPadded then S := sAlreadyPadded |
||
554 | else S := sInvalidState; |
||
555 | raise EDECException.Create(S); |
||
556 | end; |
||
557 | end; |
||
558 | |||
559 | constructor TDECCipher.Create; |
||
560 | var |
||
561 | MustUserSaved: Boolean; |
||
562 | begin |
||
563 | inherited Create; |
||
564 | with Context do |
||
565 | begin |
||
566 | FBufferSize := BufferSize; |
||
567 | FUserSize := UserSize; |
||
568 | MustUserSaved := UserSave; |
||
569 | end; |
||
570 | FDataSize := FBufferSize * 3 + FUserSize; |
||
571 | if MustUserSaved then Inc(FDataSize, FUserSize); |
||
572 | ReallocMem(FData, FDataSize); |
||
573 | FVector := @FData[0]; |
||
574 | FFeedback := @FVector[FBufferSize]; |
||
575 | FBuffer := @FFeedback[FBufferSize]; |
||
576 | FUser := @FBuffer[FBufferSize]; |
||
577 | if MustUserSaved then FUserSave := @PByteArray(FUser)[FUserSize] |
||
578 | else FUserSave := nil; |
||
579 | Protect; |
||
580 | end; |
||
581 | |||
582 | destructor TDECCipher.Destroy; |
||
583 | begin |
||
584 | Protect; |
||
585 | ReallocMem(FData, 0); |
||
586 | FVector := nil; |
||
587 | FFeedback := nil; |
||
588 | FBuffer := nil; |
||
589 | FUser := nil; |
||
590 | FUserSave := nil; |
||
591 | inherited Destroy; |
||
592 | end; |
||
593 | |||
594 | procedure TDECCipher.Init(const Key; Size: Integer; const IVector; IVectorSize: Integer; IFiller: Byte); |
||
595 | begin |
||
596 | Protect; |
||
597 | |||
598 | if Size > Context.KeySize then |
||
599 | raise EDECException.Create(sKeyMaterialToLarge); |
||
600 | if IVectorSize > FBufferSize then |
||
601 | raise EDECException.Create(sIVMaterialToLarge); |
||
602 | |||
603 | DoInit(Key, Size); |
||
604 | if FUserSave <> nil then |
||
605 | Move(FUser^, FUserSave^, FUserSize); |
||
606 | |||
607 | FillChar(FVector^, FBufferSize, IFiller); |
||
608 | if IVectorSize = 0 then |
||
609 | begin |
||
610 | DoEncode(FVector, FVector, FBufferSize); |
||
611 | if FUserSave <> nil then Move(FUserSave^, FUser^, FUserSize); |
||
612 | end else Move(IVector, FVector^, IVectorSize); |
||
613 | Move(FVector^, FFeedback^, FBufferSize); |
||
614 | FState := csInitialized; |
||
615 | end; |
||
616 | |||
617 | procedure TDECCipher.Init(const Key: Binary; const IVector: Binary; IFiller: Byte); |
||
618 | begin |
||
619 | Init(Key[1], Length(Key), IVector[1], Length(IVector), IFiller); |
||
620 | end; |
||
621 | |||
622 | procedure TDECCipher.Done; |
||
623 | begin |
||
624 | if FState <> csDone then |
||
625 | begin |
||
626 | FState := csDone; |
||
627 | FBufferIndex := 0; |
||
628 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
629 | Move(FVector^, FFeedback^, FBufferSize); |
||
630 | if FUserSave <> nil then |
||
631 | Move(FUserSave^, FUser^, FUserSize); |
||
632 | end; |
||
633 | end; |
||
634 | |||
635 | procedure TDECCipher.Protect; |
||
636 | begin |
||
637 | FState := csNew; |
||
638 | ProtectBuffer(FData[0], FDataSize); |
||
639 | end; |
||
640 | |||
641 | procedure InvalidMessageLength(Cipher: TDECCipher); |
||
642 | begin |
||
643 | with Cipher do |
||
644 | raise EDECException.CreateFmt(sInvalidMessageLength, |
||
645 | [TypInfo.GetEnumName(TypeInfo(TCipherMode), Integer(FMode)), Context.BlockSize]); |
||
646 | end; |
||
647 | |||
648 | procedure TDECCipher.Encode(const Source; var Dest; DataSize: Integer); |
||
649 | |||
650 | procedure EncodeECBx(S,D: PByteArray; Size: Integer); |
||
651 | var |
||
652 | I: Integer; |
||
653 | begin |
||
654 | if Context.BlockSize = 1 then |
||
655 | begin |
||
656 | DoEncode(S, D, Size); |
||
657 | FState := csEncode; |
||
658 | end else |
||
659 | begin |
||
660 | Dec(Size, FBufferSize); |
||
661 | I := 0; |
||
662 | while I <= Size do |
||
663 | begin |
||
664 | DoEncode(@S[I], @D[I], FBufferSize); |
||
665 | Inc(I, FBufferSize); |
||
666 | end; |
||
667 | Dec(Size, I - FBufferSize); |
||
668 | if Size > 0 then |
||
669 | if Size mod Context.BlockSize = 0 then |
||
670 | begin |
||
671 | DoEncode(@S[I], @D[I], Size); |
||
672 | FState := csEncode; |
||
673 | end else |
||
674 | begin |
||
675 | FState := csPadded; |
||
676 | InvalidMessageLength(Self); |
||
677 | end; |
||
678 | end; |
||
679 | end; |
||
680 | |||
681 | procedure EncodeCFB8(S,D: PByteArray; Size: Integer); |
||
682 | // CFB-8 |
||
683 | var |
||
684 | I: Integer; |
||
685 | begin |
||
686 | I := 0; |
||
687 | while I < Size do |
||
688 | begin |
||
689 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
690 | Move(FFeedback[1], FFeedback[0], FBufferSize -1); |
||
691 | D[I] := S[I] xor FBuffer[0]; |
||
692 | FFeedback[FBufferSize -1] := D[I]; |
||
693 | Inc(I); |
||
694 | end; |
||
695 | FState := csEncode; |
||
696 | end; |
||
697 | |||
698 | procedure EncodeOFB8(S,D: PByteArray; Size: Integer); |
||
699 | var |
||
700 | I: Integer; |
||
701 | begin |
||
702 | I := 0; |
||
703 | while I < Size do |
||
704 | begin |
||
705 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
706 | Move(FFeedback[1], FFeedback[0], FBufferSize -1); |
||
707 | FFeedback[FBufferSize -1] := FBuffer[0]; |
||
708 | D[I] := S[I] xor FBuffer[0]; |
||
709 | Inc(I); |
||
710 | end; |
||
711 | FState := csEncode; |
||
712 | end; |
||
713 | |||
714 | procedure EncodeCFS8(S,D: PByteArray; Size: Integer); |
||
715 | // CFS-8, CTS as CFB |
||
716 | var |
||
717 | I: Integer; |
||
718 | begin |
||
719 | I := 0; |
||
720 | while I < Size do |
||
721 | begin |
||
722 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
723 | D[I] := S[I] xor FBuffer[0]; |
||
724 | Move(FFeedback[1], FFeedback[0], FBufferSize -1); |
||
725 | FFeedback[FBufferSize -1] := FFeedback[FBufferSize -1] xor D[I]; |
||
726 | Inc(I); |
||
727 | end; |
||
728 | FState := csEncode; |
||
729 | end; |
||
730 | |||
731 | procedure EncodeCFBx(S,D: PByteArray; Size: Integer); |
||
732 | // CFB-BlockSize |
||
733 | var |
||
734 | I: Integer; |
||
735 | F: PByteArray; |
||
736 | begin |
||
737 | FState := csEncode; |
||
738 | if FBufferIndex > 0 then |
||
739 | begin |
||
740 | I := FBufferSize - FBufferIndex; |
||
741 | if I > Size then I := Size; |
||
742 | XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]); |
||
743 | Move(D[0], FFeedback[FBufferIndex], I); |
||
744 | Inc(FBufferIndex, I); |
||
745 | if FBufferIndex < FBufferSize then Exit; |
||
746 | Dec(Size, I); |
||
747 | S := @S[I]; |
||
748 | D := @D[I]; |
||
749 | FBufferIndex := 0 |
||
750 | end; |
||
751 | Dec(Size, FBufferSize); |
||
752 | F := FFeedback; |
||
753 | I := 0; |
||
754 | while I < Size do |
||
755 | begin |
||
756 | DoEncode(F, FBuffer, FBufferSize); |
||
757 | XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]); |
||
758 | F := @D[I]; |
||
759 | Inc(I, FBufferSize); |
||
760 | end; |
||
761 | if F <> FFeedback then |
||
762 | Move(F^, FFeedback^, FBufferSize); |
||
763 | Dec(Size, I - FBufferSize); |
||
764 | if Size > 0 then |
||
765 | begin |
||
766 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
767 | XORBuffers(S[I], FBuffer[0], Size, D[I]); |
||
768 | Move(D[I], FFeedback[0], Size); |
||
769 | FBufferIndex := Size; |
||
770 | end; |
||
771 | end; |
||
772 | |||
773 | procedure EncodeOFBx(S,D: PByteArray; Size: Integer); |
||
774 | // OFB-BlockSize |
||
775 | var |
||
776 | I: Integer; |
||
777 | begin |
||
778 | FState := csEncode; |
||
779 | if FBufferIndex > 0 then |
||
780 | begin |
||
781 | I := FBufferSize - FBufferIndex; |
||
782 | if I > Size then I := Size; |
||
783 | XORBuffers(S[0], FFeedback[FBufferIndex], I, D[0]); |
||
784 | Inc(FBufferIndex, I); |
||
785 | if FBufferIndex < FBufferSize then Exit; |
||
786 | Dec(Size, I); |
||
787 | S := @S[I]; |
||
788 | D := @D[I]; |
||
789 | FBufferIndex := 0 |
||
790 | end; |
||
791 | Dec(Size, FBufferSize); |
||
792 | I := 0; |
||
793 | while I < Size do |
||
794 | begin |
||
795 | DoEncode(FFeedback, FFeedback, FBufferSize); |
||
796 | XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]); |
||
797 | Inc(I, FBufferSize); |
||
798 | end; |
||
799 | Dec(Size, I - FBufferSize); |
||
800 | if Size > 0 then |
||
801 | begin |
||
802 | DoEncode(FFeedback, FFeedback, FBufferSize); |
||
803 | XORBuffers(S[I], FFeedback[0], Size, D[I]); |
||
804 | FBufferIndex := Size; |
||
805 | end; |
||
806 | end; |
||
807 | |||
808 | procedure EncodeCFSx(S,D: PByteArray; Size: Integer); |
||
809 | // CFS-BlockSize |
||
810 | var |
||
811 | I: Integer; |
||
812 | begin |
||
813 | FState := csEncode; |
||
814 | if FBufferIndex > 0 then |
||
815 | begin |
||
816 | I := FBufferSize - FBufferIndex; |
||
817 | if I > Size then I := Size; |
||
818 | XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]); |
||
819 | XORBuffers(D[0], FFeedback[FBufferIndex], I, FFeedback[FBufferIndex]); |
||
820 | Inc(FBufferIndex, I); |
||
821 | if FBufferIndex < FBufferSize then Exit; |
||
822 | Dec(Size, I); |
||
823 | S := @S[I]; |
||
824 | D := @D[I]; |
||
825 | FBufferIndex := 0 |
||
826 | end; |
||
827 | Dec(Size, FBufferSize); |
||
828 | I := 0; |
||
829 | while I < Size do |
||
830 | begin |
||
831 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
832 | XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]); |
||
833 | XORBuffers(D[I], FFeedback[0], FBufferSize, FFeedback[0]); |
||
834 | Inc(I, FBufferSize); |
||
835 | end; |
||
836 | Dec(Size, I - FBufferSize); |
||
837 | if Size > 0 then |
||
838 | begin |
||
839 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
840 | XORBuffers(S[I], FBuffer[0], Size, D[I]); |
||
841 | XORBuffers(D[I], FFeedback[0], Size, FFeedback[0]); |
||
842 | FBufferIndex := Size; |
||
843 | end; |
||
844 | end; |
||
845 | |||
846 | procedure EncodeCBCx(S,D: PByteArray; Size: Integer); |
||
847 | var |
||
848 | F: PByteArray; |
||
849 | I: Integer; |
||
850 | begin |
||
851 | Dec(Size, FBufferSize); |
||
852 | F := FFeedback; |
||
853 | I := 0; |
||
854 | while I <= Size do |
||
855 | begin |
||
856 | XORBuffers(S[I], F[0], FBufferSize, D[I]); |
||
857 | F := @D[I]; |
||
858 | DoEncode(F, F, FBufferSize); |
||
859 | Inc(I, FBufferSize); |
||
860 | end; |
||
861 | if F <> FFeedback then |
||
862 | Move(F[0], FFeedback[0], FBufferSize); |
||
863 | Dec(Size, I - FBufferSize); |
||
864 | if Size > 0 then |
||
865 | begin // padding |
||
866 | EncodeCFB8(@S[I], @D[I], Size); |
||
867 | FState := csPadded; |
||
868 | end else FState := csEncode; |
||
869 | end; |
||
870 | |||
871 | procedure EncodeCTSx(S,D: PByteArray; Size: Integer); |
||
872 | var |
||
873 | I: Integer; |
||
874 | begin |
||
875 | Dec(Size, FBufferSize); |
||
876 | I := 0; |
||
877 | while I <= Size do |
||
878 | begin |
||
879 | XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]); |
||
880 | DoEncode(@D[I], @D[I], FBufferSize); |
||
881 | XORBuffers(D[I], FFeedback[0], FBufferSize, FFeedback[0]); |
||
882 | Inc(I, FBufferSize); |
||
883 | end; |
||
884 | Dec(Size, I - FBufferSize); |
||
885 | if Size > 0 then |
||
886 | begin // padding |
||
887 | EncodeCFS8(@S[I], @D[I], Size); |
||
888 | FState := csPadded; |
||
889 | end else FState := csEncode; |
||
890 | end; |
||
891 | |||
892 | begin |
||
893 | CheckState([csInitialized, csEncode, csDone]); |
||
894 | case FMode of |
||
895 | cmECBx: EncodeECBx(@Source, @Dest, DataSize); |
||
896 | cmCBCx: EncodeCBCx(@Source, @Dest, DataSize); |
||
897 | cmCTSx: EncodeCTSx(@Source, @Dest, DataSize); |
||
898 | cmCFB8: EncodeCFB8(@Source, @Dest, DataSize); |
||
899 | cmCFBx: EncodeCFBx(@Source, @Dest, DataSize); |
||
900 | cmOFB8: EncodeOFB8(@Source, @Dest, DataSize); |
||
901 | cmOFBx: EncodeOFBx(@Source, @Dest, DataSize); |
||
902 | cmCFS8: EncodeCFS8(@Source, @Dest, DataSize); |
||
903 | cmCFSx: EncodeCFSx(@Source, @Dest, DataSize); |
||
904 | end; |
||
905 | end; |
||
906 | |||
907 | procedure TDECCipher.Decode(const Source; var Dest; DataSize: Integer); |
||
908 | |||
909 | procedure DecodeECBx(S,D: PByteArray; Size: Integer); |
||
910 | var |
||
911 | I: Integer; |
||
912 | begin |
||
913 | if Context.BlockSize = 1 then |
||
914 | begin |
||
915 | DoDecode(S, D, Size); |
||
916 | FState := csDecode; |
||
917 | end else |
||
918 | begin |
||
919 | Dec(Size, FBufferSize); |
||
920 | I := 0; |
||
921 | while I <= Size do |
||
922 | begin |
||
923 | DoDecode(@S[I], @D[I], FBufferSize); |
||
924 | Inc(I, FBufferSize); |
||
925 | end; |
||
926 | Dec(Size, I - FBufferSize); |
||
927 | if Size > 0 then |
||
928 | if Size mod Context.BlockSize = 0 then |
||
929 | begin |
||
930 | DoDecode(@S[I], @D[I], Size); |
||
931 | FState := csDecode; |
||
932 | end else |
||
933 | begin |
||
934 | FState := csPadded; |
||
935 | InvalidMessageLength(Self); |
||
936 | end; |
||
937 | end; |
||
938 | end; |
||
939 | |||
940 | procedure DecodeCFB8(S,D: PByteArray; Size: Integer); |
||
941 | // CFB-8 |
||
942 | var |
||
943 | I: Integer; |
||
944 | begin |
||
945 | I := 0; |
||
946 | while I < Size do |
||
947 | begin |
||
948 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
949 | Move(FFeedback[1], FFeedback[0], FBufferSize -1); |
||
950 | FFeedback[FBufferSize -1] := S[I]; |
||
951 | D[I] := S[I] xor FBuffer[0]; |
||
952 | Inc(I); |
||
953 | end; |
||
954 | FState := csDecode; |
||
955 | end; |
||
956 | |||
957 | procedure DecodeOFB8(S,D: PByteArray; Size: Integer); |
||
958 | // same as EncodeOFB |
||
959 | var |
||
960 | I: Integer; |
||
961 | begin |
||
962 | I := 0; |
||
963 | while I < Size do |
||
964 | begin |
||
965 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
966 | Move(FFeedback[1], FFeedback[0], FBufferSize -1); |
||
967 | FFeedback[FBufferSize -1] := FBuffer[0]; |
||
968 | D[I] := S[I] xor FBuffer[0]; |
||
969 | Inc(I); |
||
970 | end; |
||
971 | FState := csDecode; |
||
972 | end; |
||
973 | |||
974 | procedure DecodeCFS8(S,D: PByteArray; Size: Integer); |
||
975 | var |
||
976 | I: Integer; |
||
977 | begin |
||
978 | I := 0; |
||
979 | while I < Size do |
||
980 | begin |
||
981 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
982 | Move(FFeedback[1], FFeedback[0], FBufferSize -1); |
||
983 | FFeedback[FBufferSize -1] := FFeedback[FBufferSize -1] xor S[I]; |
||
984 | D[I] := S[I] xor FBuffer[0]; |
||
985 | Inc(I); |
||
986 | end; |
||
987 | FState := csDecode; |
||
988 | end; |
||
989 | |||
990 | procedure DecodeCFBx(S,D: PByteArray; Size: Integer); |
||
991 | // CFB-BlockSize |
||
992 | var |
||
993 | I: Integer; |
||
994 | F: PByteArray; |
||
995 | begin |
||
996 | FState := csDecode; |
||
997 | if FBufferIndex > 0 then |
||
998 | begin // remain bytes of last decode |
||
999 | I := FBufferSize - FBufferIndex; |
||
1000 | if I > Size then I := Size; |
||
1001 | Move(S[0], FFeedback[FBufferIndex], I); |
||
1002 | XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]); |
||
1003 | Inc(FBufferIndex, I); |
||
1004 | if FBufferIndex < FBufferSize then Exit; |
||
1005 | Dec(Size, I); |
||
1006 | S := @S[I]; |
||
1007 | D := @D[I]; |
||
1008 | FBufferIndex := 0 |
||
1009 | end; |
||
1010 | // process chunks of FBufferSize bytes |
||
1011 | Dec(Size, FBufferSize); |
||
1012 | I := 0; |
||
1013 | if S <> D then |
||
1014 | begin |
||
1015 | F := FFeedback; |
||
1016 | while I < Size do |
||
1017 | begin |
||
1018 | DoEncode(F, FBuffer, FBufferSize); |
||
1019 | XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]); |
||
1020 | F := @S[I]; |
||
1021 | Inc(I, FBufferSize); |
||
1022 | end; |
||
1023 | if F <> FFeedback then |
||
1024 | Move(F^, FFeedback^, FBufferSize); |
||
1025 | end else |
||
1026 | while I < Size do |
||
1027 | begin |
||
1028 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
1029 | Move(S[I], FFeedback[0], FBufferSize); |
||
1030 | XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]); |
||
1031 | Inc(I, FBufferSize); |
||
1032 | end; |
||
1033 | Dec(Size, I - FBufferSize); |
||
1034 | if Size > 0 then |
||
1035 | begin // remain bytes |
||
1036 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
1037 | Move(S[I], FFeedback[0], Size); |
||
1038 | XORBuffers(S[I], FBuffer[0], Size, D[I]); |
||
1039 | FBufferIndex := Size; |
||
1040 | end; |
||
1041 | end; |
||
1042 | |||
1043 | procedure DecodeOFBx(S,D: PByteArray; Size: Integer); |
||
1044 | // OFB-BlockSize, same as EncodeOFBx |
||
1045 | var |
||
1046 | I: Integer; |
||
1047 | begin |
||
1048 | FState := csDecode; |
||
1049 | if FBufferIndex > 0 then |
||
1050 | begin |
||
1051 | I := FBufferSize - FBufferIndex; |
||
1052 | if I > Size then I := Size; |
||
1053 | XORBuffers(S[0], FFeedback[FBufferIndex], I, D[0]); |
||
1054 | Inc(FBufferIndex, I); |
||
1055 | if FBufferIndex < FBufferSize then Exit; |
||
1056 | Dec(Size, I); |
||
1057 | S := @S[I]; |
||
1058 | D := @D[I]; |
||
1059 | FBufferIndex := 0 |
||
1060 | end; |
||
1061 | Dec(Size, FBufferSize); |
||
1062 | I := 0; |
||
1063 | while I < Size do |
||
1064 | begin |
||
1065 | DoEncode(FFeedback, FFeedback, FBufferSize); |
||
1066 | XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]); |
||
1067 | Inc(I, FBufferSize); |
||
1068 | end; |
||
1069 | Dec(Size, I - FBufferSize); |
||
1070 | if Size > 0 then |
||
1071 | begin |
||
1072 | DoEncode(FFeedback, FFeedback, FBufferSize); |
||
1073 | XORBuffers(S[I], FFeedback[0], Size, D[I]); |
||
1074 | FBufferIndex := Size; |
||
1075 | end; |
||
1076 | end; |
||
1077 | |||
1078 | procedure DecodeCFSx(S,D: PByteArray; Size: Integer); |
||
1079 | // CFS-BlockSize |
||
1080 | var |
||
1081 | I: Integer; |
||
1082 | begin |
||
1083 | FState := csDecode; |
||
1084 | if FBufferIndex > 0 then |
||
1085 | begin // remain bytes of last decode |
||
1086 | I := FBufferSize - FBufferIndex; |
||
1087 | if I > Size then I := Size; |
||
1088 | XORBuffers(S[0], FFeedback[FBufferIndex], I, FFeedback[FBufferIndex]); |
||
1089 | XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]); |
||
1090 | Inc(FBufferIndex, I); |
||
1091 | if FBufferIndex < FBufferSize then Exit; |
||
1092 | Dec(Size, I); |
||
1093 | S := @S[I]; |
||
1094 | D := @D[I]; |
||
1095 | FBufferIndex := 0 |
||
1096 | end; |
||
1097 | // process chunks of FBufferSize bytes |
||
1098 | Dec(Size, FBufferSize); |
||
1099 | I := 0; |
||
1100 | while I < Size do |
||
1101 | begin |
||
1102 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
1103 | XORBuffers(S[I], FFeedback[0], FBufferSize, FFeedback[0]); |
||
1104 | XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]); |
||
1105 | Inc(I, FBufferSize); |
||
1106 | end; |
||
1107 | Dec(Size, I - FBufferSize); |
||
1108 | if Size > 0 then |
||
1109 | begin // remain bytes |
||
1110 | DoEncode(FFeedback, FBuffer, FBufferSize); |
||
1111 | XORBuffers(S[I], FFeedback[0], Size, FFeedback[0]); |
||
1112 | XORBuffers(S[I], FBuffer[0], Size, D[I]); |
||
1113 | FBufferIndex := Size; |
||
1114 | end; |
||
1115 | end; |
||
1116 | |||
1117 | procedure DecodeCBCx(S,D: PByteArray; Size: Integer); |
||
1118 | var |
||
1119 | I: Integer; |
||
1120 | F,B,T: PByteArray; |
||
1121 | begin |
||
1122 | Dec(Size, FBufferSize); |
||
1123 | F := FFeedback; |
||
1124 | I := 0; |
||
1125 | if S = D then |
||
1126 | begin |
||
1127 | B := FBuffer; |
||
1128 | while I <= Size do |
||
1129 | begin |
||
1130 | Move(S[I], B[0], FBufferSize); |
||
1131 | DoDecode(@S[I], @S[I], FBufferSize); |
||
1132 | XORBuffers(S[I], F[0], FBufferSize, S[I]); |
||
1133 | T := F; |
||
1134 | F := B; |
||
1135 | B := T; |
||
1136 | Inc(I, FBufferSize); |
||
1137 | end; |
||
1138 | end else |
||
1139 | while I <= Size do |
||
1140 | begin |
||
1141 | DoDecode(@S[I], @D[I], FBufferSize); |
||
1142 | XORBuffers(F[0], D[I], FBufferSize, D[I]); |
||
1143 | F := @S[I]; |
||
1144 | Inc(I, FBufferSize); |
||
1145 | end; |
||
1146 | if F <> FFeedback then |
||
1147 | Move(F[0], FFeedback[0], FBufferSize); |
||
1148 | Dec(Size, I - FBufferSize); |
||
1149 | if Size > 0 then |
||
1150 | begin |
||
1151 | DecodeCFB8(@S[I], @D[I], Size); |
||
1152 | FState := csPadded; |
||
1153 | end else FState := csDecode; |
||
1154 | end; |
||
1155 | |||
1156 | procedure DecodeCTSx(S,D: PByteArray; Size: Integer); |
||
1157 | var |
||
1158 | I: Integer; |
||
1159 | F,B,T: PByteArray; |
||
1160 | begin |
||
1161 | Dec(Size, FBufferSize); |
||
1162 | F := FFeedback; |
||
1163 | B := FBuffer; |
||
1164 | I := 0; |
||
1165 | while I <= Size do |
||
1166 | begin |
||
1167 | XORBuffers(S[I], F[0], FBufferSize, B[0]); |
||
1168 | DoDecode(@S[I], @D[I], FBufferSize); |
||
1169 | XORBuffers(D[I], F[0], FBufferSize, D[I]); |
||
1170 | T := B; |
||
1171 | B := F; |
||
1172 | F := T; |
||
1173 | Inc(I, FBufferSize); |
||
1174 | end; |
||
1175 | if F <> FFeedback then |
||
1176 | Move(F[0], FFeedback[0], FBufferSize); |
||
1177 | Dec(Size, I - FBufferSize); |
||
1178 | if Size > 0 then |
||
1179 | begin |
||
1180 | DecodeCFS8(@S[I], @D[I], Size); |
||
1181 | FState := csPadded; |
||
1182 | end else FState := csDecode; |
||
1183 | end; |
||
1184 | |||
1185 | begin |
||
1186 | CheckState([csInitialized, csDecode, csDone]); |
||
1187 | case FMode of |
||
1188 | cmECBx: DecodeECBx(@Source, @Dest, DataSize); |
||
1189 | cmCBCx: DecodeCBCx(@Source, @Dest, DataSize); |
||
1190 | cmCTSx: DecodeCTSx(@Source, @Dest, DataSize); |
||
1191 | cmCFB8: DecodeCFB8(@Source, @Dest, DataSize); |
||
1192 | cmCFBx: DecodeCFBx(@Source, @Dest, DataSize); |
||
1193 | cmOFB8: DecodeOFB8(@Source, @Dest, DataSize); |
||
1194 | cmOFBx: DecodeOFBx(@Source, @Dest, DataSize); |
||
1195 | cmCFS8: DecodeCFS8(@Source, @Dest, DataSize); |
||
1196 | cmCFSx: DecodeCFSx(@Source, @Dest, DataSize); |
||
1197 | end; |
||
1198 | end; |
||
1199 | |||
1200 | function TDECCipher.EncodeBinary(const Source: Binary; Format: TDECFormatClass): Binary; |
||
1201 | begin |
||
1202 | SetLength(Result, Length(Source)); |
||
1203 | Encode(Source[1], Result[1], Length(Source)); |
||
1204 | Result := ValidFormat(Format).Encode(Result); |
||
1205 | end; |
||
1206 | |||
1207 | function TDECCipher.DecodeBinary(const Source: Binary; Format: TDECFormatClass): Binary; |
||
1208 | begin |
||
1209 | Result := ValidFormat(Format).Decode(Source); |
||
1210 | Decode(Result[1], Result[1], Length(Result)); |
||
1211 | end; |
||
1212 | |||
1213 | procedure DoCodeStream(Source,Dest: TStream; Size: Int64; BlockSize: Integer; const Proc: TDECCipherCodeEvent; const Progress: IDECProgress); |
||
1214 | var |
||
1215 | Buffer: Binary; |
||
1216 | BufferSize,Bytes: Integer; |
||
1217 | Min,Max,Pos: Int64; |
||
1218 | begin |
||
1219 | Pos := Source.Position; |
||
1220 | if Size < 0 then Size := Source.Size - Pos; |
||
1221 | Min := Pos; |
||
1222 | Max := Pos + Size; |
||
1223 | if Size > 0 then |
||
1224 | try |
||
1225 | if StreamBufferSize <= 0 then StreamBufferSize := 8192; |
||
1226 | BufferSize := StreamBufferSize mod BlockSize; |
||
1227 | if BufferSize = 0 then BufferSize := StreamBufferSize |
||
1228 | else BufferSize := StreamBufferSize + BlockSize - BufferSize; |
||
1229 | if Size > BufferSize then SetLength(Buffer, BufferSize) |
||
1230 | else SetLength(Buffer, Size); |
||
1231 | while Size > 0 do |
||
1232 | begin |
||
1233 | if Assigned(Progress) then Progress.Process(Min, Max, Pos); |
||
1234 | Bytes := BufferSize; |
||
1235 | if Bytes > Size then Bytes := Size; |
||
1236 | Source.ReadBuffer(Buffer[1], Bytes); |
||
1237 | Proc(Buffer[1], Buffer[1], Bytes); |
||
1238 | Dest.WriteBuffer(Buffer[1], Bytes); |
||
1239 | Dec(Size, Bytes); |
||
1240 | Inc(Pos, Bytes); |
||
1241 | end; |
||
1242 | finally |
||
1243 | ProtectBinary(Buffer); |
||
1244 | if Assigned(Progress) then Progress.Process(Min, Max, Max); |
||
1245 | end; |
||
1246 | end; |
||
1247 | |||
1248 | procedure DoCodeFile(const Source,Dest: String; BlockSize: Integer; const Proc: TDECCipherCodeEvent; const Progress: IDECProgress); |
||
1249 | var |
||
1250 | S,D: TStream; |
||
1251 | begin |
||
1252 | S := TFileStream.Create(Source, fmOpenRead or fmShareDenyNone); |
||
1253 | try |
||
1254 | D := TFileStream.Create(Dest, fmCreate); |
||
1255 | try |
||
1256 | DoCodeStream(S, D, S.Size, BlockSize, Proc, Progress); |
||
1257 | finally |
||
1258 | D.Free; |
||
1259 | end; |
||
1260 | finally |
||
1261 | S.Free; |
||
1262 | end; |
||
1263 | end; |
||
1264 | |||
1265 | procedure TDECCipher.EncodeFile(const Source, Dest: String; const Progress: IDECProgress); |
||
1266 | begin |
||
1267 | DoCodeFile(Source, Dest, Context.BlockSize, Encode, Progress); |
||
1268 | end; |
||
1269 | |||
1270 | procedure TDECCipher.DecodeFile(const Source, Dest: String; const Progress: IDECProgress); |
||
1271 | begin |
||
1272 | DoCodeFile(Source, Dest, Context.BlockSize, Decode, Progress); |
||
1273 | end; |
||
1274 | |||
1275 | procedure TDECCipher.EncodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress); |
||
1276 | begin |
||
1277 | DoCodeStream(Source, Dest, DataSize, Context.BlockSize, Encode, Progress); |
||
1278 | end; |
||
1279 | |||
1280 | procedure TDECCipher.DecodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress); |
||
1281 | begin |
||
1282 | DoCodeStream(Source, Dest, DataSize, Context.BlockSize, Decode, Progress); |
||
1283 | end; |
||
1284 | |||
1285 | function TDECCipher.CalcMAC(Format: TDECFormatClass): Binary; |
||
1286 | begin |
||
1287 | Done; |
||
1288 | if FMode in [cmECBx] then raise EDECException.Create(sInvalidMACMode) |
||
1289 | else Result := ValidFormat(Format).Encode(FBuffer^, FBufferSize); |
||
1290 | end; |
||
1291 | |||
1292 | // .TCipher_Null |
||
1293 | class function TCipher_Null.Context: TCipherContext; |
||
1294 | begin |
||
1295 | Result.KeySize := 0; |
||
1296 | Result.BlockSize := 1; |
||
1297 | Result.BufferSize := 32; |
||
1298 | Result.UserSize := 0; |
||
1299 | Result.UserSave := False; |
||
1300 | end; |
||
1301 | |||
1302 | procedure TCipher_Null.DoInit(const Key; Size: Integer); |
||
1303 | begin |
||
1304 | end; |
||
1305 | |||
1306 | procedure TCipher_Null.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
1307 | begin |
||
1308 | if Source <> Dest then Move(Source^, Dest^, Size); |
||
1309 | end; |
||
1310 | |||
1311 | procedure TCipher_Null.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
1312 | begin |
||
1313 | if Source <> Dest then Move(Source^, Dest^, Size); |
||
1314 | end; |
||
1315 | |||
1316 | // .TCipher_Blowfish |
||
1317 | |||
1318 | {$IFDEF UseASM} |
||
1319 | {$IFDEF 486GE} |
||
1320 | {$DEFINE Blowfish_asm} |
||
1321 | {$ENDIF} |
||
1322 | {$ENDIF} |
||
1323 | |||
1324 | type |
||
1325 | PBlowfish = ^TBlowfish; |
||
1326 | TBlowfish = array[0..3, 0..255] of LongWord; |
||
1327 | |||
1328 | class function TCipher_Blowfish.Context: TCipherContext; |
||
1329 | begin |
||
1330 | Result.KeySize := 56; |
||
1331 | Result.BufferSize := 8; |
||
1332 | Result.BlockSize := 8; |
||
1333 | Result.UserSize := SizeOf(Blowfish_Data) + SizeOf(Blowfish_Key); |
||
1334 | Result.UserSave := False; |
||
1335 | end; |
||
1336 | |||
1337 | procedure TCipher_Blowfish.DoInit(const Key; Size: Integer); |
||
1338 | var |
||
1339 | I,J: Integer; |
||
1340 | B: array[0..1] of LongWord; |
||
1341 | K: PByteArray; |
||
1342 | P: PLongArray; |
||
1343 | S: PBlowfish; |
||
1344 | begin |
||
1345 | K := @Key; |
||
1346 | S := FUser; |
||
1347 | P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data)); |
||
1348 | Move(Blowfish_Data, S^, SizeOf(Blowfish_Data)); |
||
1349 | Move(Blowfish_Key, P^, Sizeof(Blowfish_Key)); |
||
1350 | J := 0; |
||
1351 | if Size > 0 then |
||
1352 | for I := 0 to 17 do |
||
1353 | begin |
||
1354 | P[I] := P[I] xor (K[(J + 0) mod Size] shl 24 + |
||
1355 | K[(J + 1) mod Size] shl 16 + |
||
1356 | K[(J + 2) mod Size] shl 8 + |
||
1357 | K[(J + 3) mod Size] shl 0); |
||
1358 | J := (J + 4) mod Size; |
||
1359 | end; |
||
1360 | FillChar(B, SizeOf(B), 0); |
||
1361 | for I := 0 to 8 do |
||
1362 | begin |
||
1363 | DoEncode(@B, @B, SizeOf(B)); |
||
1364 | P[I * 2 + 0] := SwapLong(B[0]); |
||
1365 | P[I * 2 + 1] := SwapLong(B[1]); |
||
1366 | end; |
||
1367 | for I := 0 to 3 do |
||
1368 | for J := 0 to 127 do |
||
1369 | begin |
||
1370 | DoEncode(@B, @B, SizeOf(B)); |
||
1371 | S[I, J * 2 + 0] := SwapLong(B[0]); |
||
1372 | S[I, J * 2 + 1] := SwapLong(B[1]); |
||
1373 | end; |
||
1374 | FillChar(B, SizeOf(B), 0); |
||
1375 | end; |
||
1376 | |||
1377 | procedure TCipher_Blowfish.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
1378 | {$IFDEF Blowfish_asm} // specialy for CPU >= 486 |
||
1379 | // Source = EDX, Dest=ECX, Size on Stack |
||
1380 | asm |
||
1381 | PUSH EDI |
||
1382 | PUSH ESI |
||
1383 | PUSH EBX |
||
1384 | PUSH EBP |
||
1385 | PUSH ECX |
||
1386 | MOV ESI,[EAX].TCipher_Blowfish.FUser |
||
1387 | MOV EBX,[EDX + 0] // A |
||
1388 | MOV EBP,[EDX + 4] // B |
||
1389 | BSWAP EBX // CPU >= 486 |
||
1390 | BSWAP EBP |
||
1391 | XOR EBX,[ESI + 4 * 256 * 4] |
||
1392 | XOR EDI,EDI |
||
1393 | @@1: MOV EAX,EBX |
||
1394 | SHR EBX,16 |
||
1395 | MOVZX ECX,BH |
||
1396 | AND EBX,0FFh |
||
1397 | MOV ECX,[ESI + ECX * 4 + 1024 * 0] |
||
1398 | MOV EBX,[ESI + EBX * 4 + 1024 * 1] |
||
1399 | MOVZX EDX,AH |
||
1400 | ADD EBX,ECX |
||
1401 | MOVZX ECX,AL |
||
1402 | MOV EDX,[ESI + EDX * 4 + 1024 * 2] |
||
1403 | MOV ECX,[ESI + ECX * 4 + 1024 * 3] |
||
1404 | XOR EBX,EDX |
||
1405 | XOR EBP,[ESI + 4 * 256 * 4 + 4 + EDI * 4] |
||
1406 | ADD EBX,ECX |
||
1407 | INC EDI |
||
1408 | XOR EBX,EBP |
||
1409 | TEST EDI,010h |
||
1410 | MOV EBP,EAX |
||
1411 | JZ @@1 |
||
1412 | POP EAX |
||
1413 | XOR EBP,[ESI + 4 * 256 * 4 + 17 * 4] |
||
1414 | BSWAP EBX |
||
1415 | BSWAP EBP |
||
1416 | MOV [EAX + 4],EBX |
||
1417 | MOV [EAX + 0],EBP |
||
1418 | POP EBP |
||
1419 | POP EBX |
||
1420 | POP ESI |
||
1421 | POP EDI |
||
1422 | end; |
||
1423 | {$ELSE} |
||
1424 | var |
||
1425 | I,A,B: LongWord; |
||
1426 | P: PLongArray; |
||
1427 | D: PBlowfish; |
||
1428 | begin |
||
1429 | Assert(Size = Context.BlockSize); |
||
1430 | |||
1431 | D := FUser; |
||
1432 | P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data)); |
||
1433 | A := SwapLong(PLongArray(Source)[0]) xor P[0]; P := @P[1]; |
||
1434 | B := SwapLong(PLongArray(Source)[1]); |
||
1435 | for I := 0 to 7 do |
||
1436 | begin |
||
1437 | B := B xor P[0] xor (D[0, A shr 24 ] + |
||
1438 | D[1, A shr 16 and $FF] xor |
||
1439 | D[2, A shr 8 and $FF] + |
||
1440 | D[3, A and $FF]); |
||
1441 | |||
1442 | A := A xor P[1] xor (D[0, B shr 24 ] + |
||
1443 | D[1, B shr 16 and $FF] xor |
||
1444 | D[2, B shr 8 and $FF] + |
||
1445 | D[3, B and $FF]); |
||
1446 | P := @P[2]; |
||
1447 | end; |
||
1448 | PLongArray(Dest)[0] := SwapLong(B xor P[0]); |
||
1449 | PLongArray(Dest)[1] := SwapLong(A); |
||
1450 | end; |
||
1451 | {$ENDIF} |
||
1452 | |||
1453 | procedure TCipher_Blowfish.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
1454 | {$IFDEF Blowfish_asm} |
||
1455 | asm |
||
1456 | PUSH EDI |
||
1457 | PUSH ESI |
||
1458 | PUSH EBX |
||
1459 | PUSH EBP |
||
1460 | PUSH ECX |
||
1461 | MOV ESI,[EAX].TCipher_Blowfish.FUser |
||
1462 | MOV EBX,[EDX + 0] // A |
||
1463 | MOV EBP,[EDX + 4] // B |
||
1464 | BSWAP EBX |
||
1465 | BSWAP EBP |
||
1466 | XOR EBX,[ESI + 4 * 256 * 4 + 17 * 4] |
||
1467 | MOV EDI,16 |
||
1468 | @@1: MOV EAX,EBX |
||
1469 | SHR EBX,16 |
||
1470 | MOVZX ECX,BH |
||
1471 | MOVZX EDX,BL |
||
1472 | MOV EBX,[ESI + ECX * 4 + 1024 * 0] |
||
1473 | MOV EDX,[ESI + EDX * 4 + 1024 * 1] |
||
1474 | MOVZX ECX,AH |
||
1475 | LEA EBX,[EBX + EDX] |
||
1476 | MOVZX EDX,AL |
||
1477 | MOV ECX,[ESI + ECX * 4 + 1024 * 2] |
||
1478 | MOV EDX,[ESI + EDX * 4 + 1024 * 3] |
||
1479 | XOR EBX,ECX |
||
1480 | XOR EBP,[ESI + 4 * 256 * 4 + EDI * 4] |
||
1481 | LEA EBX,[EBX + EDX] |
||
1482 | XOR EBX,EBP |
||
1483 | DEC EDI |
||
1484 | MOV EBP,EAX |
||
1485 | JNZ @@1 |
||
1486 | POP EAX |
||
1487 | XOR EBP,[ESI + 4 * 256 * 4] |
||
1488 | BSWAP EBX |
||
1489 | BSWAP EBP |
||
1490 | MOV [EAX + 0],EBP |
||
1491 | MOV [EAX + 4],EBX |
||
1492 | POP EBP |
||
1493 | POP EBX |
||
1494 | POP ESI |
||
1495 | POP EDI |
||
1496 | end; |
||
1497 | {$ELSE} |
||
1498 | var |
||
1499 | I,A,B: LongWord; |
||
1500 | P: PLongArray; |
||
1501 | D: PBlowfish; |
||
1502 | begin |
||
1503 | Assert(Size = Context.BlockSize); |
||
1504 | |||
1505 | D := FUser; |
||
1506 | P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data) + SizeOf(Blowfish_Key) - SizeOf(Integer)); |
||
1507 | A := SwapLong(PLongArray(Source)[0]) xor P[0]; |
||
1508 | B := SwapLong(PLongArray(Source)[1]); |
||
1509 | for I := 0 to 7 do |
||
1510 | begin |
||
1511 | Dec(PLongWord(P), 2); |
||
1512 | B := B xor P[1] xor (D[0, A shr 24 ] + |
||
1513 | D[1, A shr 16 and $FF] xor |
||
1514 | D[2, A shr 8 and $FF] + |
||
1515 | D[3, A and $FF]); |
||
1516 | A := A xor P[0] xor (D[0, B shr 24 ] + |
||
1517 | D[1, B shr 16 and $FF] xor |
||
1518 | D[2, B shr 8 and $FF] + |
||
1519 | D[3, B and $FF]); |
||
1520 | end; |
||
1521 | Dec(PLongWord(P)); |
||
1522 | PLongArray(Dest)[0] := SwapLong(B xor P[0]); |
||
1523 | PLongArray(Dest)[1] := SwapLong(A); |
||
1524 | end; |
||
1525 | {$ENDIF} |
||
1526 | |||
1527 | // .TCipher_Twofish |
||
1528 | type |
||
1529 | PTwofishBox = ^TTwofishBox; |
||
1530 | TTwofishBox = array[0..3, 0..255] of Longword; |
||
1531 | |||
1532 | TLongRec = record |
||
1533 | case Integer of |
||
1534 | 0: (L: Longword); |
||
1535 | 1: (A,B,C,D: Byte); |
||
1536 | end; |
||
1537 | |||
1538 | class function TCipher_Twofish.Context: TCipherContext; |
||
1539 | begin |
||
1540 | Result.KeySize := 32; |
||
1541 | Result.BufferSize := 16; |
||
1542 | Result.BlockSize := 16; |
||
1543 | Result.UserSize := 4256; |
||
1544 | Result.UserSave := False; |
||
1545 | end; |
||
1546 | |||
1547 | procedure TCipher_Twofish.DoInit(const Key; Size: Integer); |
||
1548 | var |
||
1549 | BoxKey: array[0..3] of TLongRec; |
||
1550 | SubKey: PLongArray; |
||
1551 | Box: PTwofishBox; |
||
1552 | |||
1553 | procedure SetupKey; |
||
1554 | |||
1555 | function Encode(K0, K1: Integer): Integer; |
||
1556 | var |
||
1557 | R, I, J, G2, G3: Integer; |
||
1558 | B: byte; |
||
1559 | begin |
||
1560 | R := 0; |
||
1561 | for I := 0 to 1 do |
||
1562 | begin |
||
1563 | if I <> 0 then R := R xor K0 else R := R xor K1; |
||
1564 | for J := 0 to 3 do |
||
1565 | begin |
||
1566 | B := R shr 24; |
||
1567 | if B and $80 <> 0 then G2 := (B shl 1 xor $014D) and $FF |
||
1568 | else G2 := B shl 1 and $FF; |
||
1569 | if B and 1 <> 0 then G3 := (B shr 1 and $7F) xor $014D shr 1 xor G2 |
||
1570 | else G3 := (B shr 1 and $7F) xor G2; |
||
1571 | R := R shl 8 xor G3 shl 24 xor G2 shl 16 xor G3 shl 8 xor B; |
||
1572 | end; |
||
1573 | end; |
||
1574 | Result := R; |
||
1575 | end; |
||
1576 | |||
1577 | function F32(X: Integer; K: array of Integer): Integer; |
||
1578 | var |
||
1579 | A, B, C, D: LongWord; |
||
1580 | begin |
||
1581 | A := X and $FF; |
||
1582 | B := X shr 8 and $FF; |
||
1583 | C := X shr 16 and $FF; |
||
1584 | D := X shr 24; |
||
1585 | if Size = 32 then |
||
1586 | begin |
||
1587 | A := Twofish_8x8[1, A] xor K[3] and $FF; |
||
1588 | B := Twofish_8x8[0, B] xor K[3] shr 8 and $FF; |
||
1589 | C := Twofish_8x8[0, C] xor K[3] shr 16 and $FF; |
||
1590 | D := Twofish_8x8[1, D] xor K[3] shr 24; |
||
1591 | end; |
||
1592 | if Size >= 24 then |
||
1593 | begin |
||
1594 | A := Twofish_8x8[1, A] xor K[2] and $FF; |
||
1595 | B := Twofish_8x8[1, B] xor K[2] shr 8 and $FF; |
||
1596 | C := Twofish_8x8[0, C] xor K[2] shr 16 and $FF; |
||
1597 | D := Twofish_8x8[0, D] xor K[2] shr 24; |
||
1598 | end; |
||
1599 | A := Twofish_8x8[0, A] xor K[1] and $FF; |
||
1600 | B := Twofish_8x8[1, B] xor K[1] shr 8 and $FF; |
||
1601 | C := Twofish_8x8[0, C] xor K[1] shr 16 and $FF; |
||
1602 | D := Twofish_8x8[1, D] xor K[1] shr 24; |
||
1603 | |||
1604 | A := Twofish_8x8[0, A] xor K[0] and $FF; |
||
1605 | B := Twofish_8x8[0, B] xor K[0] shr 8 and $FF; |
||
1606 | C := Twofish_8x8[1, C] xor K[0] shr 16 and $FF; |
||
1607 | D := Twofish_8x8[1, D] xor K[0] shr 24; |
||
1608 | |||
1609 | Result := Twofish_Data[0, A] xor Twofish_Data[1, B] xor |
||
1610 | Twofish_Data[2, C] xor Twofish_Data[3, D]; |
||
1611 | end; |
||
1612 | |||
1613 | var |
||
1614 | I,J,A,B: Integer; |
||
1615 | E,O: array[0..3] of Integer; |
||
1616 | K: array[0..7] of Integer; |
||
1617 | begin |
||
1618 | FillChar(K, SizeOf(K), 0); |
||
1619 | Move(Key, K, Size); |
||
1620 | if Size <= 16 then Size := 16 else |
||
1621 | if Size <= 24 then Size := 24 |
||
1622 | else Size := 32; |
||
1623 | J := Size shr 3 - 1; |
||
1624 | for I := 0 to J do |
||
1625 | begin |
||
1626 | E[I] := K[I shl 1]; |
||
1627 | O[I] := K[I shl 1 + 1]; |
||
1628 | BoxKey[J].L := Encode(E[I], O[I]); |
||
1629 | Dec(J); |
||
1630 | end; |
||
1631 | J := 0; |
||
1632 | for I := 0 to 19 do |
||
1633 | begin |
||
1634 | A := F32(J, E); |
||
1635 | B := F32(J + $01010101, O); |
||
1636 | B := B shl 8 or B shr 24; |
||
1637 | SubKey[I shl 1] := A + B; |
||
1638 | B := A + B shl 1; // here buggy instead shr 1 it's correct shl 1 |
||
1639 | SubKey[I shl 1 + 1] := B shl 9 or B shr 23; |
||
1640 | Inc(J, $02020202); |
||
1641 | end; |
||
1642 | end; |
||
1643 | |||
1644 | procedure DoXOR(D, S: PLongArray; Value: LongWord); |
||
1645 | var |
||
1646 | I: LongWord; |
||
1647 | begin |
||
1648 | Value := (Value and $FF) * $01010101; |
||
1649 | for I := 0 to 63 do D[I] := S[I] xor Value; |
||
1650 | end; |
||
1651 | |||
1652 | procedure SetupBox128; |
||
1653 | var |
||
1654 | L: array[0..255] of Byte; |
||
1655 | A,I: Integer; |
||
1656 | begin |
||
1657 | DoXOR(@L, @Twofish_8x8[0], BoxKey[1].L); |
||
1658 | A := BoxKey[0].A; |
||
1659 | for I := 0 to 255 do |
||
1660 | Box[0, I] := Twofish_Data[0, Twofish_8x8[0, L[I]] xor A]; |
||
1661 | DoXOR(@L, @Twofish_8x8[1], BoxKey[1].L shr 8); |
||
1662 | A := BoxKey[0].B; |
||
1663 | for I := 0 to 255 do |
||
1664 | Box[1, I] := Twofish_Data[1, Twofish_8x8[0, L[I]] xor A]; |
||
1665 | DoXOR(@L, @Twofish_8x8[0], BoxKey[1].L shr 16); |
||
1666 | A := BoxKey[0].C; |
||
1667 | for I := 0 to 255 do |
||
1668 | Box[2, I] := Twofish_Data[2, Twofish_8x8[1, L[I]] xor A]; |
||
1669 | DoXOR(@L, @Twofish_8x8[1], BoxKey[1].L shr 24); |
||
1670 | A := BoxKey[0].D; |
||
1671 | for I := 0 to 255 do |
||
1672 | Box[3, I] := Twofish_Data[3, Twofish_8x8[1, L[I]] xor A]; |
||
1673 | end; |
||
1674 | |||
1675 | procedure SetupBox192; |
||
1676 | var |
||
1677 | L: array[0..255] of Byte; |
||
1678 | A,B,I: Integer; |
||
1679 | begin |
||
1680 | DoXOR(@L, @Twofish_8x8[1], BoxKey[2].L); |
||
1681 | A := BoxKey[0].A; |
||
1682 | B := BoxKey[1].A; |
||
1683 | for I := 0 to 255 do |
||
1684 | Box[0, I] := Twofish_Data[0, Twofish_8x8[0, Twofish_8x8[0, L[I]] xor B] xor A]; |
||
1685 | DoXOR(@L, @Twofish_8x8[1], BoxKey[2].L shr 8); |
||
1686 | A := BoxKey[0].B; |
||
1687 | B := BoxKey[1].B; |
||
1688 | for I := 0 to 255 do |
||
1689 | Box[1, I] := Twofish_Data[1, Twofish_8x8[0, Twofish_8x8[1, L[I]] xor B] xor A]; |
||
1690 | DoXOR(@L, @Twofish_8x8[0], BoxKey[2].L shr 16); |
||
1691 | A := BoxKey[0].C; |
||
1692 | B := BoxKey[1].C; |
||
1693 | for I := 0 to 255 do |
||
1694 | Box[2, I] := Twofish_Data[2, Twofish_8x8[1, Twofish_8x8[0, L[I]] xor B] xor A]; |
||
1695 | DoXOR(@L ,@Twofish_8x8[0], BoxKey[2].L shr 24); |
||
1696 | A := BoxKey[0].D; |
||
1697 | B := BoxKey[1].D; |
||
1698 | for I := 0 to 255 do |
||
1699 | Box[3, I] := Twofish_Data[3, Twofish_8x8[1, Twofish_8x8[1, L[I]] xor B] xor A]; |
||
1700 | end; |
||
1701 | |||
1702 | procedure SetupBox256; |
||
1703 | var |
||
1704 | L: array[0..255] of Byte; |
||
1705 | K: array[0..255] of Byte; |
||
1706 | A,B,I: Integer; |
||
1707 | begin |
||
1708 | DoXOR(@K, @Twofish_8x8[1], BoxKey[3].L); |
||
1709 | for I := 0 to 255 do L[I] := Twofish_8x8[1, K[I]]; |
||
1710 | DoXOR(@L, @L, BoxKey[2].L); |
||
1711 | A := BoxKey[0].A; |
||
1712 | B := BoxKey[1].A; |
||
1713 | for I := 0 to 255 do |
||
1714 | Box[0, I] := Twofish_Data[0, Twofish_8x8[0, Twofish_8x8[0, L[I]] xor B] xor A]; |
||
1715 | DoXOR(@K, @Twofish_8x8[0], BoxKey[3].L shr 8); |
||
1716 | for I := 0 to 255 do L[I] := Twofish_8x8[1, K[I]]; |
||
1717 | DoXOR(@L, @L, BoxKey[2].L shr 8); |
||
1718 | A := BoxKey[0].B; |
||
1719 | B := BoxKey[1].B; |
||
1720 | for I := 0 to 255 do |
||
1721 | Box[1, I] := Twofish_Data[1, Twofish_8x8[0, Twofish_8x8[1, L[I]] xor B] xor A]; |
||
1722 | DoXOR(@K, @Twofish_8x8[0],BoxKey[3].L shr 16); |
||
1723 | for I := 0 to 255 do L[I] := Twofish_8x8[0, K[I]]; |
||
1724 | DoXOR(@L, @L, BoxKey[2].L shr 16); |
||
1725 | A := BoxKey[0].C; |
||
1726 | B := BoxKey[1].C; |
||
1727 | for I := 0 to 255 do |
||
1728 | Box[2, I] := Twofish_Data[2, Twofish_8x8[1, Twofish_8x8[0, L[I]] xor B] xor A]; |
||
1729 | DoXOR(@K, @Twofish_8x8[1], BoxKey[3].L shr 24); |
||
1730 | for I := 0 to 255 do L[I] := Twofish_8x8[0, K[I]]; |
||
1731 | DoXOR(@L, @L, BoxKey[2].L shr 24); |
||
1732 | A := BoxKey[0].D; |
||
1733 | B := BoxKey[1].D; |
||
1734 | for I := 0 to 255 do |
||
1735 | Box[3, I] := Twofish_Data[3, Twofish_8x8[1, Twofish_8x8[1, L[I]] xor B] xor A]; |
||
1736 | end; |
||
1737 | |||
1738 | begin |
||
1739 | SubKey := FUser; |
||
1740 | Box := @SubKey[40]; |
||
1741 | SetupKey; |
||
1742 | if Size = 16 then SetupBox128 else |
||
1743 | if Size = 24 then SetupBox192 |
||
1744 | else SetupBox256; |
||
1745 | end; |
||
1746 | |||
1747 | procedure TCipher_Twofish.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
1748 | var |
||
1749 | S: PLongArray; |
||
1750 | Box: PTwofishBox; |
||
1751 | I,X,Y: LongWord; |
||
1752 | A,B,C,D: TLongRec; |
||
1753 | begin |
||
1754 | Assert(Size = Context.BlockSize); |
||
1755 | |||
1756 | S := FUser; |
||
1757 | A.L := PLongArray(Source)[0] xor S[0]; |
||
1758 | B.L := PLongArray(Source)[1] xor S[1]; |
||
1759 | C.L := PLongArray(Source)[2] xor S[2]; |
||
1760 | D.L := PLongArray(Source)[3] xor S[3]; |
||
1761 | |||
1762 | Box := @S[40]; |
||
1763 | S := @S[8]; |
||
1764 | for I := 0 to 7 do |
||
1765 | begin |
||
1766 | X := Box[0, A.A] xor Box[1, A.B] xor Box[2, A.C] xor Box[3, A.D]; |
||
1767 | Y := Box[1, B.A] xor Box[2, B.B] xor Box[3, B.C] xor Box[0, B.D]; |
||
1768 | D.L := D.L shl 1 or D.L shr 31; |
||
1769 | C.L := C.L xor (X + Y + S[0]); |
||
1770 | D.L := D.L xor (X + Y shl 1 + S[1]); |
||
1771 | C.L := C.L shr 1 or C.L shl 31; |
||
1772 | |||
1773 | X := Box[0, C.A] xor Box[1, C.B] xor Box[2, C.C] xor Box[3, C.D]; |
||
1774 | Y := Box[1, D.A] xor Box[2, D.B] xor Box[3, D.C] xor Box[0, D.D]; |
||
1775 | B.L := B.L shl 1 or B.L shr 31; |
||
1776 | A.L := A.L xor (X + Y + S[2]); |
||
1777 | B.L := B.L xor (X + Y shl 1 + S[3]); |
||
1778 | A.L := A.L shr 1 or A.L shl 31; |
||
1779 | |||
1780 | S := @S[4]; |
||
1781 | end; |
||
1782 | S := FUser; |
||
1783 | PLongArray(Dest)[0] := C.L xor S[4]; |
||
1784 | PLongArray(Dest)[1] := D.L xor S[5]; |
||
1785 | PLongArray(Dest)[2] := A.L xor S[6]; |
||
1786 | PLongArray(Dest)[3] := B.L xor S[7]; |
||
1787 | end; |
||
1788 | |||
1789 | procedure TCipher_Twofish.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
1790 | var |
||
1791 | S: PLongArray; |
||
1792 | Box: PTwofishBox; |
||
1793 | I,X,Y: LongWord; |
||
1794 | A,B,C,D: TLongRec; |
||
1795 | begin |
||
1796 | Assert(Size = Context.BlockSize); |
||
1797 | |||
1798 | S := FUser; |
||
1799 | Box := @S[40]; |
||
1800 | C.L := PLongArray(Source)[0] xor S[4]; |
||
1801 | D.L := PLongArray(Source)[1] xor S[5]; |
||
1802 | A.L := PLongArray(Source)[2] xor S[6]; |
||
1803 | B.L := PLongArray(Source)[3] xor S[7]; |
||
1804 | S := @S[36]; |
||
1805 | for I := 0 to 7 do |
||
1806 | begin |
||
1807 | X := Box[0, C.A] xor Box[1, C.B] xor Box[2, C.C] xor Box[3, C.D]; |
||
1808 | Y := Box[0, D.D] xor Box[1, D.A] xor Box[2, D.B] xor Box[3, D.C]; |
||
1809 | A.L := A.L shl 1 or A.L shr 31; |
||
1810 | B.L := B.L xor (X + Y shl 1 + S[3]); |
||
1811 | A.L := A.L xor (X + Y + S[2]); |
||
1812 | B.L := B.L shr 1 or B.L shl 31; |
||
1813 | |||
1814 | X := Box[0, A.A] xor Box[1, A.B] xor Box[2, A.C] xor Box[3, A.D]; |
||
1815 | Y := Box[0, B.D] xor Box[1, B.A] xor Box[2, B.B] xor Box[3, B.C]; |
||
1816 | C.L := C.L shl 1 or C.L shr 31; |
||
1817 | D.L := D.L xor (X + Y shl 1 + S[1]); |
||
1818 | C.L := C.L xor (X + Y + S[0]); |
||
1819 | D.L := D.L shr 1 or D.L shl 31; |
||
1820 | |||
1821 | Dec(PLongWord(S), 4); |
||
1822 | end; |
||
1823 | S := FUser; |
||
1824 | PLongArray(Dest)[0] := A.L xor S[0]; |
||
1825 | PLongArray(Dest)[1] := B.L xor S[1]; |
||
1826 | PLongArray(Dest)[2] := C.L xor S[2]; |
||
1827 | PLongArray(Dest)[3] := D.L xor S[3]; |
||
1828 | end; |
||
1829 | |||
1830 | // .TCipher_IDEA |
||
1831 | class function TCipher_IDEA.Context: TCipherContext; |
||
1832 | begin |
||
1833 | Result.KeySize := 16; |
||
1834 | Result.BufferSize := 8; |
||
1835 | Result.BlockSize := 8; |
||
1836 | Result.UserSize := 208; |
||
1837 | Result.UserSave := False; |
||
1838 | end; |
||
1839 | |||
1840 | procedure TCipher_IDEA.DoInit(const Key; Size: Integer); |
||
1841 | |||
1842 | function IDEAInv(X: Word): Word; |
||
1843 | var |
||
1844 | A, B, C, D: Word; |
||
1845 | begin |
||
1846 | if X <= 1 then |
||
1847 | begin |
||
1848 | Result := X; |
||
1849 | Exit; |
||
1850 | end; |
||
1851 | A := 1; |
||
1852 | B := $10001 div X; |
||
1853 | C := $10001 mod X; |
||
1854 | while C <> 1 do |
||
1855 | begin |
||
1856 | D := X div C; |
||
1857 | X := X mod C; |
||
1858 | Inc(A, B * D); |
||
1859 | if X = 1 then |
||
1860 | begin |
||
1861 | Result := A; |
||
1862 | Exit; |
||
1863 | end; |
||
1864 | D := C div X; |
||
1865 | C := C mod X; |
||
1866 | Inc(B, A * D); |
||
1867 | end; |
||
1868 | Result := 1 - B; |
||
1869 | end; |
||
1870 | |||
1871 | var |
||
1872 | I: Integer; |
||
1873 | E: PWordArray; |
||
1874 | A,B,C: Word; |
||
1875 | K,D: PWordArray; |
||
1876 | begin |
||
1877 | E := FUser; |
||
1878 | Move(Key, E^, Size); |
||
1879 | for I := 0 to 7 do E[I] := Swap(E[I]); |
||
1880 | for I := 0 to 39 do |
||
1881 | E[I + 8] := E[I and not 7 + (I + 1) and 7] shl 9 or |
||
1882 | E[I and not 7 + (I + 2) and 7] shr 7; |
||
1883 | for I := 41 to 44 do |
||
1884 | E[I + 7] := E[I] shl 9 or E[I + 1] shr 7; |
||
1885 | K := E; |
||
1886 | D := @E[100]; |
||
1887 | A := IDEAInv(K[0]); |
||
1888 | B := 0 - K[1]; |
||
1889 | C := 0 - K[2]; |
||
1890 | D[3] := IDEAInv(K[3]); |
||
1891 | D[2] := C; |
||
1892 | D[1] := B; |
||
1893 | D[0] := A; |
||
1894 | Inc(PWord(K), 4); |
||
1895 | for I := 1 to 8 do |
||
1896 | begin |
||
1897 | Dec(PWord(D), 6); |
||
1898 | A := K[0]; |
||
1899 | D[5] := K[1]; |
||
1900 | D[4] := A; |
||
1901 | A := IDEAInv(K[2]); |
||
1902 | B := 0 - K[3]; |
||
1903 | C := 0 - K[4]; |
||
1904 | D[3] := IDEAInv(K[5]); |
||
1905 | D[2] := B; |
||
1906 | D[1] := C; |
||
1907 | D[0] := A; |
||
1908 | Inc(PWord(K), 6); |
||
1909 | end; |
||
1910 | A := D[2]; |
||
1911 | D[2] := D[1]; |
||
1912 | D[1] := A; |
||
1913 | end; |
||
1914 | |||
1915 | function IDEAMul(X,Y: LongWord): LongWord; |
||
1916 | asm |
||
1917 | AND EAX,0FFFFh |
||
1918 | JZ @@1 |
||
1919 | AND EDX,0FFFFh |
||
1920 | JZ @@1 |
||
1921 | MUL EDX |
||
1922 | MOV EDX,EAX |
||
1923 | MOV ECX,EAX |
||
1924 | SHR EDX,16 |
||
1925 | SUB EAX,EDX |
||
1926 | SUB CX,AX |
||
1927 | ADC EAX,0 |
||
1928 | RET |
||
1929 | @@1: LEA EAX,[EAX + EDX -1] |
||
1930 | NEG EAX |
||
1931 | end; |
||
1932 | |||
1933 | procedure IDEACipher(Source, Dest: PLongArray; Key: PWordArray); |
||
1934 | var |
||
1935 | I: LongWord; |
||
1936 | X,Y,A,B,C,D: LongWord; |
||
1937 | begin |
||
1938 | I := SwapLong(Source[0]); |
||
1939 | A := I shr 16; |
||
1940 | B := I and $FFFF; |
||
1941 | I := SwapLong(Source[1]); |
||
1942 | C := I shr 16; |
||
1943 | D := I and $FFFF; |
||
1944 | for I := 0 to 7 do |
||
1945 | begin |
||
1946 | A := IDEAMul(A, Key[0]); |
||
1947 | Inc(B, Key[1]); |
||
1948 | Inc(C, Key[2]); |
||
1949 | D := IDEAMul(D, Key[3]); |
||
1950 | Y := C xor A; |
||
1951 | Y := IDEAMul(Y, Key[4]); |
||
1952 | X := B xor D + Y; |
||
1953 | X := IDEAMul(X, Key[5]); |
||
1954 | Inc(Y, X); |
||
1955 | A := A xor X; |
||
1956 | D := D xor Y; |
||
1957 | Y := B xor Y; |
||
1958 | B := C xor X; |
||
1959 | C := Y; |
||
1960 | Key := @Key[6]; |
||
1961 | end; |
||
1962 | Dest[0] := SwapLong(IDEAMul(A, Key[0]) shl 16 or (C + Key[1]) and $FFFF); |
||
1963 | Dest[1] := SwapLong((B + Key[2]) shl 16 or IDEAMul(D, Key[3]) and $FFFF); |
||
1964 | end; |
||
1965 | |||
1966 | procedure TCipher_IDEA.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
1967 | begin |
||
1968 | Assert(Size = Context.BlockSize); |
||
1969 | |||
1970 | IDEACipher(Source, Dest, FUser); |
||
1971 | end; |
||
1972 | |||
1973 | procedure TCipher_IDEA.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
1974 | begin |
||
1975 | Assert(Size = Context.BlockSize); |
||
1976 | |||
1977 | IDEACipher(Source, Dest, @PLongArray(FUser)[26]); |
||
1978 | end; |
||
1979 | |||
1980 | // .TCipher_Cast256 |
||
1981 | class function TCipher_Cast256.Context: TCipherContext; |
||
1982 | begin |
||
1983 | Result.KeySize := 32; |
||
1984 | Result.BlockSize := 16; |
||
1985 | Result.BufferSize := 16; |
||
1986 | Result.UserSize := 384; |
||
1987 | Result.UserSave := False; |
||
1988 | end; |
||
1989 | |||
1990 | procedure TCipher_Cast256.DoInit(const Key; Size: Integer); |
||
1991 | var |
||
1992 | X: array[0..7] of LongWord; |
||
1993 | M, R, I, J, T: LongWord; |
||
1994 | K: PLongArray; |
||
1995 | begin |
||
1996 | FillChar(X, SizeOf(X), 0); |
||
1997 | Move(Key, X, Size); |
||
1998 | SwapLongBuffer(X, X, 8); |
||
1999 | K := FUser; |
||
2000 | M := $5A827999; |
||
2001 | R := 19; |
||
2002 | for I := 0 to 11 do |
||
2003 | begin |
||
2004 | for J := 0 to 1 do |
||
2005 | begin |
||
2006 | T := M + X[7]; |
||
2007 | T := T shl R or T shr (32 - R); |
||
2008 | X[6] := X[6] xor (Cast256_Data[0, T shr 24] xor |
||
2009 | Cast256_Data[1, T shr 16 and $FF] - |
||
2010 | Cast256_Data[2, T shr 8 and $FF] + |
||
2011 | Cast256_Data[3, T and $FF]); |
||
2012 | Inc(M, $6ED9EBA1); |
||
2013 | Inc(R, 17); |
||
2014 | T := M xor X[6]; |
||
2015 | T := T shl R or T shr (32 - R); |
||
2016 | X[5] := X[5] xor (Cast256_Data[0, T shr 24] - |
||
2017 | Cast256_Data[1, T shr 16 and $FF] + |
||
2018 | Cast256_Data[2, T shr 8 and $FF] xor |
||
2019 | Cast256_Data[3, T and $FF]); |
||
2020 | Inc(M, $6ED9EBA1); |
||
2021 | Inc(R, 17); |
||
2022 | T := M - X[5]; |
||
2023 | T := T shl R or T shr (32 - R); |
||
2024 | X[4] := X[4] xor (Cast256_Data[0, T shr 24] + |
||
2025 | Cast256_Data[1, T shr 16 and $FF] xor |
||
2026 | Cast256_Data[2, T shr 8 and $FF] - |
||
2027 | Cast256_Data[3, T and $FF]); |
||
2028 | Inc(M, $6ED9EBA1); |
||
2029 | Inc(R, 17); |
||
2030 | T := M + X[4]; |
||
2031 | T := T shl R or T shr (32 - R); |
||
2032 | X[3] := X[3] xor (Cast256_Data[0, T shr 24] xor |
||
2033 | Cast256_Data[1, T shr 16 and $FF] - |
||
2034 | Cast256_Data[2, T shr 8 and $FF] + |
||
2035 | Cast256_Data[3, T and $FF]); |
||
2036 | Inc(M, $6ED9EBA1); |
||
2037 | Inc(R, 17); |
||
2038 | T := M xor X[3]; |
||
2039 | T := T shl R or T shr (32 - R); |
||
2040 | X[2] := X[2] xor (Cast256_Data[0, T shr 24] - |
||
2041 | Cast256_Data[1, T shr 16 and $FF] + |
||
2042 | Cast256_Data[2, T shr 8 and $FF] xor |
||
2043 | Cast256_Data[3, T and $FF]); |
||
2044 | Inc(M, $6ED9EBA1); |
||
2045 | Inc(R, 17); |
||
2046 | T := M - X[2]; |
||
2047 | T := T shl R or T shr (32 - R); |
||
2048 | X[1] := X[1] xor (Cast256_Data[0, T shr 24] + |
||
2049 | Cast256_Data[1, T shr 16 and $FF] xor |
||
2050 | Cast256_Data[2, T shr 8 and $FF] - |
||
2051 | Cast256_Data[3, T and $FF]); |
||
2052 | Inc(M, $6ED9EBA1); |
||
2053 | Inc(R, 17); |
||
2054 | T := M + X[1]; |
||
2055 | T := T shl R or T shr (32 - R); |
||
2056 | X[0] := X[0] xor (Cast256_Data[0, T shr 24] xor |
||
2057 | Cast256_Data[1, T shr 16 and $FF] - |
||
2058 | Cast256_Data[2, T shr 8 and $FF] + |
||
2059 | Cast256_Data[3, T and $FF]); |
||
2060 | Inc(M, $6ED9EBA1); |
||
2061 | Inc(R, 17); |
||
2062 | T := M xor X[0]; |
||
2063 | T := T shl R or T shr (32 - R); |
||
2064 | X[7] := X[7] xor (Cast256_Data[0, T shr 24] - |
||
2065 | Cast256_Data[1, T shr 16 and $FF] + |
||
2066 | Cast256_Data[2, T shr 8 and $FF] xor |
||
2067 | Cast256_Data[3, T and $FF]); |
||
2068 | Inc(M, $6ED9EBA1); |
||
2069 | Inc(R, 17); |
||
2070 | end; |
||
2071 | if I < 6 then |
||
2072 | begin |
||
2073 | K[48] := X[0] and $1F; |
||
2074 | K[49] := X[2] and $1F; |
||
2075 | K[50] := X[4] and $1F; |
||
2076 | K[51] := X[6] and $1F; |
||
2077 | K[0] := X[7]; |
||
2078 | K[1] := X[5]; |
||
2079 | K[2] := X[3]; |
||
2080 | K[3] := X[1]; |
||
2081 | end else |
||
2082 | begin |
||
2083 | K[48] := X[6] and $1F; |
||
2084 | K[49] := X[4] and $1F; |
||
2085 | K[50] := X[2] and $1F; |
||
2086 | K[51] := X[0] and $1F; |
||
2087 | K[0] := X[1]; |
||
2088 | K[1] := X[3]; |
||
2089 | K[2] := X[5]; |
||
2090 | K[3] := X[7]; |
||
2091 | end; |
||
2092 | K := @K[4]; |
||
2093 | end; |
||
2094 | ProtectBuffer(X, SizeOf(X)); |
||
2095 | end; |
||
2096 | |||
2097 | procedure TCipher_Cast256.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
2098 | var |
||
2099 | I,T,A,B,C,D: LongWord; |
||
2100 | K: PLongArray; |
||
2101 | begin |
||
2102 | Assert(Size = Context.BlockSize); |
||
2103 | |||
2104 | K := FUser; |
||
2105 | SwapLongBuffer(Source^, Dest^, 4); |
||
2106 | A := PLongArray(Dest)[0]; |
||
2107 | B := PLongArray(Dest)[1]; |
||
2108 | C := PLongArray(Dest)[2]; |
||
2109 | D := PLongArray(Dest)[3]; |
||
2110 | for I := 0 to 5 do |
||
2111 | begin |
||
2112 | T := K[0] + D; |
||
2113 | T := T shl K[48] or T shr (32 - K[48]); |
||
2114 | C := C xor (Cast256_Data[0, T shr 24] xor |
||
2115 | Cast256_Data[1, T shr 16 and $FF] - |
||
2116 | Cast256_Data[2, T shr 8 and $FF] + |
||
2117 | Cast256_Data[3, T and $FF]); |
||
2118 | T := K[1] xor C; |
||
2119 | T := T shl K[49] or T shr (32 - K[49]); |
||
2120 | B := B xor (Cast256_Data[0, T shr 24] - |
||
2121 | Cast256_Data[1, T shr 16 and $FF] + |
||
2122 | Cast256_Data[2, T shr 8 and $FF] xor |
||
2123 | Cast256_Data[3, T and $FF]); |
||
2124 | T := K[2] - B; |
||
2125 | T := T shl K[50] or T shr (32 - K[50]); |
||
2126 | A := A xor (Cast256_Data[0, T shr 24] + |
||
2127 | Cast256_Data[1, T shr 16 and $FF] xor |
||
2128 | Cast256_Data[2, T shr 8 and $FF] - |
||
2129 | Cast256_Data[3, T and $FF]); |
||
2130 | T := K[3] + A; |
||
2131 | T := T shl K[51] or T shr (32 - K[51]); |
||
2132 | D := D xor (Cast256_Data[0, T shr 24] xor |
||
2133 | Cast256_Data[1, T shr 16 and $FF] - |
||
2134 | Cast256_Data[2, T shr 8 and $FF] + |
||
2135 | Cast256_Data[3, T and $FF]); |
||
2136 | K := @K[4]; |
||
2137 | end; |
||
2138 | for I := 0 to 5 do |
||
2139 | begin |
||
2140 | T := K[0] + A; |
||
2141 | T := T shl K[48] or T shr (32 - K[48]); |
||
2142 | D := D xor (Cast256_Data[0, T shr 24] xor |
||
2143 | Cast256_Data[1, T shr 16 and $FF] - |
||
2144 | Cast256_Data[2, T shr 8 and $FF] + |
||
2145 | Cast256_Data[3, T and $FF]); |
||
2146 | T := K[1] - B; |
||
2147 | T := T shl K[49] or T shr (32 - K[49]); |
||
2148 | A := A xor (Cast256_Data[0, T shr 24] + |
||
2149 | Cast256_Data[1, T shr 16 and $FF] xor |
||
2150 | Cast256_Data[2, T shr 8 and $FF] - |
||
2151 | Cast256_Data[3, T and $FF]); |
||
2152 | T := K[2] xor C; |
||
2153 | T := T shl K[50] or T shr (32 - K[50]); |
||
2154 | B := B xor (Cast256_Data[0, T shr 24] - |
||
2155 | Cast256_Data[1, T shr 16 and $FF] + |
||
2156 | Cast256_Data[2, T shr 8 and $FF] xor |
||
2157 | Cast256_Data[3, T and $FF]); |
||
2158 | T := K[3] + D; |
||
2159 | T := T shl K[51] or T shr (32 - K[51]); |
||
2160 | C := C xor (Cast256_Data[0, T shr 24] xor |
||
2161 | Cast256_Data[1, T shr 16 and $FF] - |
||
2162 | Cast256_Data[2, T shr 8 and $FF] + |
||
2163 | Cast256_Data[3, T and $FF]); |
||
2164 | K := @K[4]; |
||
2165 | end; |
||
2166 | PLongArray(Dest)[0] := A; |
||
2167 | PLongArray(Dest)[1] := B; |
||
2168 | PLongArray(Dest)[2] := C; |
||
2169 | PLongArray(Dest)[3] := D; |
||
2170 | SwapLongBuffer(Dest^, Dest^, 4); |
||
2171 | end; |
||
2172 | |||
2173 | procedure TCipher_Cast256.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
2174 | var |
||
2175 | I,T,A,B,C,D: LongWord; |
||
2176 | K: PLongArray; |
||
2177 | begin |
||
2178 | Assert(Size = Context.BlockSize); |
||
2179 | |||
2180 | K := @PLongArray(FUser)[44]; |
||
2181 | SwapLongBuffer(Source^, Dest^, 4); |
||
2182 | A := PLongArray(Dest)[0]; |
||
2183 | B := PLongArray(Dest)[1]; |
||
2184 | C := PLongArray(Dest)[2]; |
||
2185 | D := PLongArray(Dest)[3]; |
||
2186 | for I := 0 to 5 do |
||
2187 | begin |
||
2188 | T := K[3] + D; |
||
2189 | T := T shl K[51] or T shr (32 - K[51]); |
||
2190 | C := C xor (Cast256_Data[0, T shr 24] xor |
||
2191 | Cast256_Data[1, T shr 16 and $FF] - |
||
2192 | Cast256_Data[2, T shr 8 and $FF] + |
||
2193 | Cast256_Data[3, T and $FF]); |
||
2194 | T := K[2] xor C; |
||
2195 | T := T shl K[50] or T shr (32 - K[50]); |
||
2196 | B := B xor (Cast256_Data[0, T shr 24] - |
||
2197 | Cast256_Data[1, T shr 16 and $FF] + |
||
2198 | Cast256_Data[2, T shr 8 and $FF] xor |
||
2199 | Cast256_Data[3, T and $FF]); |
||
2200 | T := K[1] - B; |
||
2201 | T := T shl K[49] or T shr (32 - K[49]); |
||
2202 | A := A xor (Cast256_Data[0, T shr 24] + |
||
2203 | Cast256_Data[1, T shr 16 and $FF] xor |
||
2204 | Cast256_Data[2, T shr 8 and $FF] - |
||
2205 | Cast256_Data[3, T and $FF]); |
||
2206 | T := K[0] + A; |
||
2207 | T := T shl K[48] or T shr (32 - K[48]); |
||
2208 | D := D xor (Cast256_Data[0, T shr 24] xor |
||
2209 | Cast256_Data[1, T shr 16 and $FF] - |
||
2210 | Cast256_Data[2, T shr 8 and $FF] + |
||
2211 | Cast256_Data[3, T and $FF]); |
||
2212 | Dec(PLongWord(K), 4); |
||
2213 | end; |
||
2214 | for I := 0 to 5 do |
||
2215 | begin |
||
2216 | T := K[3] + A; |
||
2217 | T := T shl K[51] or T shr (32 - K[51]); |
||
2218 | D := D xor (Cast256_Data[0, T shr 24] xor |
||
2219 | Cast256_Data[1, T shr 16 and $FF] - |
||
2220 | Cast256_Data[2, T shr 8 and $FF] + |
||
2221 | Cast256_Data[3, T and $FF]); |
||
2222 | T := K[2] - B; |
||
2223 | T := T shl K[50] or T shr (32 - K[50]); |
||
2224 | A := A xor (Cast256_Data[0, T shr 24] + |
||
2225 | Cast256_Data[1, T shr 16 and $FF] xor |
||
2226 | Cast256_Data[2, T shr 8 and $FF] - |
||
2227 | Cast256_Data[3, T and $FF]); |
||
2228 | T := K[1] xor C; |
||
2229 | T := T shl K[49] or T shr (32 - K[49]); |
||
2230 | B := B xor (Cast256_Data[0, T shr 24] - |
||
2231 | Cast256_Data[1, T shr 16 and $FF] + |
||
2232 | Cast256_Data[2, T shr 8 and $FF] xor |
||
2233 | Cast256_Data[3, T and $FF]); |
||
2234 | T := K[0] + D; |
||
2235 | T := T shl K[48] or T shr (32 - K[48]); |
||
2236 | C := C xor (Cast256_Data[0, T shr 24] xor |
||
2237 | Cast256_Data[1, T shr 16 and $FF] - |
||
2238 | Cast256_Data[2, T shr 8 and $FF] + |
||
2239 | Cast256_Data[3, T and $FF]); |
||
2240 | Dec(PLongWord(K), 4); |
||
2241 | end; |
||
2242 | PLongArray(Dest)[0] := A; |
||
2243 | PLongArray(Dest)[1] := B; |
||
2244 | PLongArray(Dest)[2] := C; |
||
2245 | PLongArray(Dest)[3] := D; |
||
2246 | SwapLongBuffer(Dest^, Dest^, 4); |
||
2247 | end; |
||
2248 | |||
2249 | // .TCipher_Mars |
||
2250 | class function TCipher_Mars.Context: TCipherContext; |
||
2251 | begin |
||
2252 | Result.KeySize := 56; |
||
2253 | Result.BlockSize := 16; |
||
2254 | Result.BufferSize := 16; |
||
2255 | Result.UserSize := 160; |
||
2256 | Result.UserSave := False; |
||
2257 | end; |
||
2258 | |||
2259 | procedure TCipher_Mars.DoInit(const Key; Size: Integer); |
||
2260 | var |
||
2261 | B: PLongArray; |
||
2262 | |||
2263 | function FixKey(K, R: LongWord): LongWord; |
||
2264 | var |
||
2265 | M1,M2: LongWord; |
||
2266 | I: LongWord; |
||
2267 | begin |
||
2268 | I := K and 3; |
||
2269 | K := K or 3; |
||
2270 | M1 := not K xor (K shl 1); |
||
2271 | M2 := M1 and (M1 shl 1); |
||
2272 | M2 := M2 and (M2 shl 2); |
||
2273 | M2 := M2 and (M2 shl 4); |
||
2274 | M2 := M2 and (M1 shl 8); |
||
2275 | M2 := M2 and $FFFFFE00; |
||
2276 | if M2 = 0 then |
||
2277 | begin |
||
2278 | Result := K; |
||
2279 | Exit; |
||
2280 | end; |
||
2281 | M1 := M2 or (M2 shr 1); |
||
2282 | M1 := M1 or (M1 shr 2); |
||
2283 | M1 := M1 or (M2 shr 4); |
||
2284 | M1 := M1 or (M1 shr 5); |
||
2285 | M1 := M1 and ((not K xor (K shl 1)) and (not K xor (K shr 1)) and $7FFFFFFC); |
||
2286 | Result := K xor ((B[265 + I] shl R or B[265 + I] shr (32 - R)) and M1); |
||
2287 | end; |
||
2288 | |||
2289 | var |
||
2290 | T: array[0..14] of LongWord; |
||
2291 | I,J,L: LongWord; |
||
2292 | U: LongWord; |
||
2293 | K: PLongArray; |
||
2294 | begin |
||
2295 | K := FUser; |
||
2296 | B := @Mars_Data; |
||
2297 | FillChar(T, SizeOf(T), 0); |
||
2298 | Move(Key, T, Size); |
||
2299 | Size := Size div 4; |
||
2300 | T[Size] := Size; |
||
2301 | for J := 0 to 3 do |
||
2302 | begin |
||
2303 | for I := 0 to 14 do |
||
2304 | begin |
||
2305 | U := T[(I + 8) mod 15] xor T[(I + 13) mod 15]; |
||
2306 | T[I] := T[I] xor (U shl 3 or U shr 29) xor (I * 4 + J); |
||
2307 | end; |
||
2308 | for L := 0 to 3 do |
||
2309 | begin |
||
2310 | for I := 0 to 14 do |
||
2311 | begin |
||
2312 | Inc(T[I], B[T[(I + 14) mod 15] and $1FF]); |
||
2313 | T[I] := T[I] shl 9 or T[I] shr 23; |
||
2314 | end; |
||
2315 | end; |
||
2316 | for I := 0 to 9 do |
||
2317 | K[(J * 10) + I] := T[(I * 4) mod 15]; |
||
2318 | end; |
||
2319 | I := 5; |
||
2320 | repeat |
||
2321 | K[I] := FixKey(K[I], K[I - 1]); |
||
2322 | Inc(I, 2); |
||
2323 | until I >= 37; |
||
2324 | end; |
||
2325 | |||
2326 | |||
2327 | procedure TCipher_Mars.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
2328 | var |
||
2329 | K: PLongArray; |
||
2330 | I,L,R,A,B,C,D: LongWord; |
||
2331 | begin |
||
2332 | Assert(Size = Context.BlockSize); |
||
2333 | |||
2334 | K := FUser; |
||
2335 | A := PLongArray(Source)[0] + K[0]; |
||
2336 | B := PLongArray(Source)[1] + K[1]; |
||
2337 | C := PLongArray(Source)[2] + K[2]; |
||
2338 | D := PLongArray(Source)[3] + K[3]; |
||
2339 | K := @K[4]; |
||
2340 | for I := 0 to 1 do |
||
2341 | begin |
||
2342 | B := B xor Mars_Data[A and $FF] + Mars_Data[A shr 8 and $FF + 256]; |
||
2343 | Inc(C, Mars_Data[A shr 16 and $FF]); |
||
2344 | D := D xor Mars_Data[A shr 24 + 256]; |
||
2345 | A := (A shr 24 or A shl 8) + D; |
||
2346 | |||
2347 | C := C xor Mars_Data[B and $FF] + Mars_Data[B shr 8 and $FF + 256]; |
||
2348 | Inc(D, Mars_Data[B shr 16 and $FF]); |
||
2349 | A := A xor Mars_Data[B shr 24 + 256]; |
||
2350 | B := (B shr 24 or B shl 8) + C; |
||
2351 | |||
2352 | D := D xor Mars_Data[C and $FF] + Mars_Data[C shr 8 and $FF + 256]; |
||
2353 | Inc(A, Mars_Data[C shr 16 and $FF]); |
||
2354 | B := B xor Mars_Data[C shr 24 + 256]; |
||
2355 | C := C shr 24 or C shl 8; |
||
2356 | |||
2357 | A := A xor Mars_Data[D and $FF] + Mars_Data[D shr 8 and $FF + 256]; |
||
2358 | Inc(B, Mars_Data[D shr 16 and $FF]); |
||
2359 | C := C xor Mars_Data[D shr 24 + 256]; |
||
2360 | D := D shr 24 or D shl 8; |
||
2361 | end; |
||
2362 | |||
2363 | for I := 0 to 3 do |
||
2364 | begin |
||
2365 | L := A + K[0]; |
||
2366 | A := A shl 13 or A shr 19; |
||
2367 | R := A * K[1]; |
||
2368 | R := R shl 5 or R shr 27; |
||
2369 | Inc(C, L shl R or L shr (32 - R)); |
||
2370 | L := Mars_Data[L and $1FF] xor R; |
||
2371 | R := R shl 5 or R shr 27; |
||
2372 | L := L xor R; |
||
2373 | L := L shl R or L shr (32 - R); |
||
2374 | |||
2375 | if I <= 1 then |
||
2376 | begin |
||
2377 | Inc(B, L); |
||
2378 | D := D xor R; |
||
2379 | end else |
||
2380 | begin |
||
2381 | Inc(D, L); |
||
2382 | B := B xor R; |
||
2383 | end; |
||
2384 | L := B + K[2]; |
||
2385 | B := B shl 13 or B shr 19; |
||
2386 | R := B * K[3]; |
||
2387 | R := R shl 5 or R shr 27; |
||
2388 | Inc(D, L shl R or L shr (32 - R)); |
||
2389 | L := Mars_Data[L and $1FF] xor R; |
||
2390 | R := R shl 5 or R shr 27; |
||
2391 | L := L xor R; |
||
2392 | L := L shl R or L shr (32 - R); |
||
2393 | if I <= 1 then |
||
2394 | begin |
||
2395 | Inc(C, L); |
||
2396 | A := A xor R; |
||
2397 | end else |
||
2398 | begin |
||
2399 | Inc(A, L); |
||
2400 | C := C xor R; |
||
2401 | end; |
||
2402 | L := C + K[4]; |
||
2403 | C := C shl 13 or C shr 19; |
||
2404 | R := C * K[5]; |
||
2405 | R := R shl 5 or R shr 27; |
||
2406 | Inc(A, L shl R or L shr (32 - R)); |
||
2407 | L := Mars_Data[L and $1FF] xor R; |
||
2408 | R := R shl 5 or R shr 27; |
||
2409 | L := L xor R; |
||
2410 | L := L shl R or L shr (32 - R); |
||
2411 | if I <= 1 then |
||
2412 | begin |
||
2413 | Inc(D, L); |
||
2414 | B := B xor R; |
||
2415 | end else |
||
2416 | begin |
||
2417 | Inc(B, L); |
||
2418 | D := D xor R; |
||
2419 | end; |
||
2420 | L := D + K[6]; |
||
2421 | D := D shl 13 or D shr 19; |
||
2422 | R := D * K[7]; |
||
2423 | R := R shl 5 or R shr 27; |
||
2424 | Inc(B, L shl R or L shr (32 - R)); |
||
2425 | L := Mars_Data[L and $1FF] xor R; |
||
2426 | R := R shl 5 or R shr 27; |
||
2427 | L := L xor R; |
||
2428 | L := L shl R or L shr (32 - R); |
||
2429 | if I <= 1 then |
||
2430 | begin |
||
2431 | Inc(A, L); |
||
2432 | C := C xor R; |
||
2433 | end else |
||
2434 | begin |
||
2435 | Inc(C, L); |
||
2436 | A := A xor R; |
||
2437 | end; |
||
2438 | K := @K[8]; |
||
2439 | end; |
||
2440 | for I := 0 to 1 do |
||
2441 | begin |
||
2442 | B := B xor Mars_Data[A and $FF + 256]; |
||
2443 | Dec(C, Mars_Data[A shr 24]); |
||
2444 | D := D - Mars_Data[A shr 16 and $FF + 256] xor Mars_Data[A shr 8 and $FF]; |
||
2445 | A := A shl 24 or A shr 8; |
||
2446 | C := C xor Mars_Data[B and $FF + 256]; |
||
2447 | Dec(D, Mars_Data[B shr 24]); |
||
2448 | A := A - Mars_Data[B shr 16 and $FF + 256] xor Mars_Data[B shr 8 and $FF]; |
||
2449 | B := B shl 24 or B shr 8; |
||
2450 | Dec(C, B); |
||
2451 | D := D xor Mars_Data[C and $FF + 256]; |
||
2452 | Dec(A, Mars_Data[C shr 24]); |
||
2453 | B := B - Mars_Data[C shr 16 and $FF + 256] xor Mars_Data[C shr 8 and $FF]; |
||
2454 | C := C shl 24 or C shr 8; |
||
2455 | Dec(D, A); |
||
2456 | A := A xor Mars_Data[D and $FF + 256]; |
||
2457 | Dec(B, Mars_Data[D shr 24]); |
||
2458 | C := C - Mars_Data[D shr 16 and $FF + 256] xor Mars_Data[D shr 8 and $FF]; |
||
2459 | D := D shl 24 or D shr 8; |
||
2460 | end; |
||
2461 | PLongArray(Dest)[0] := A - K[0]; |
||
2462 | PLongArray(Dest)[1] := B - K[1]; |
||
2463 | PLongArray(Dest)[2] := C - K[2]; |
||
2464 | PLongArray(Dest)[3] := D - K[3]; |
||
2465 | end; |
||
2466 | |||
2467 | procedure TCipher_Mars.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
2468 | var |
||
2469 | K: PLongArray; |
||
2470 | I,L,R,A,B,C,D: LongWord; |
||
2471 | begin |
||
2472 | Assert(Size = Context.BlockSize); |
||
2473 | |||
2474 | K := @PLongArray(FUser)[28]; |
||
2475 | A := PLongArray(Source)[0] + K[8]; |
||
2476 | B := PLongArray(Source)[1] + K[9]; |
||
2477 | C := PLongArray(Source)[2] + K[10]; |
||
2478 | D := PLongArray(Source)[3] + K[11]; |
||
2479 | for I := 0 to 1 do |
||
2480 | begin |
||
2481 | D := D shr 24 or D shl 8; |
||
2482 | C := C xor Mars_Data[D shr 8 and $FF] + Mars_Data[D shr 16 and $FF + 256]; |
||
2483 | Inc(B, Mars_Data[D shr 24]); |
||
2484 | A := A xor Mars_Data[D and $FF + 256]; |
||
2485 | Inc(D, A); |
||
2486 | C := C shr 24 or C shl 8; |
||
2487 | B := B xor Mars_Data[C shr 8 and $FF] + Mars_Data[C shr 16 and $FF + 256]; |
||
2488 | Inc(A, Mars_Data[C shr 24]); |
||
2489 | D := D xor Mars_Data[C and $FF + 256]; |
||
2490 | Inc(C, B); |
||
2491 | B := B shr 24 or B shl 8; |
||
2492 | A := A xor Mars_Data[B shr 8 and $FF] + Mars_Data[B shr 16 and $FF + 256]; |
||
2493 | Inc(D, Mars_Data[B shr 24]); |
||
2494 | C := C xor Mars_Data[B and $FF + 256]; |
||
2495 | A := A shr 24 or A shl 8; |
||
2496 | D := D xor Mars_Data[A shr 8 and $FF] + Mars_Data[A shr 16 and $FF + 256]; |
||
2497 | Inc(C, Mars_Data[A shr 24]); |
||
2498 | B := B xor Mars_Data[A and $FF + 256]; |
||
2499 | end; |
||
2500 | for I := 0 to 3 do |
||
2501 | begin |
||
2502 | R := D * K[7]; |
||
2503 | R := R shl 5 or R shr 27; |
||
2504 | D := D shr 13 or D shl 19; |
||
2505 | L := D + K[6]; |
||
2506 | Dec(B, L shl R or L shr (32 - R)); |
||
2507 | L := Mars_Data[L and $1FF] xor R; |
||
2508 | R := R shl 5 or R shr 27; |
||
2509 | L := L xor R; |
||
2510 | L := L shl R or L shr (32 - R); |
||
2511 | if I <= 1 then |
||
2512 | begin |
||
2513 | Dec(C, L); |
||
2514 | A := A xor R; |
||
2515 | end else |
||
2516 | begin |
||
2517 | Dec(A, L); |
||
2518 | C := C xor R; |
||
2519 | end; |
||
2520 | R := C * K[5]; |
||
2521 | R := R shl 5 or R shr 27; |
||
2522 | C := C shr 13 or C shl 19; |
||
2523 | L := C + K[4]; |
||
2524 | Dec(A, L shl R or L shr (32 - R)); |
||
2525 | L := Mars_Data[L and $1FF] xor R; |
||
2526 | R := R shl 5 or R shr 27; |
||
2527 | L := L xor R; |
||
2528 | L := L shl R or L shr (32 - R); |
||
2529 | if I <= 1 then |
||
2530 | begin |
||
2531 | Dec(B, L); |
||
2532 | D := D xor R; |
||
2533 | end else |
||
2534 | begin |
||
2535 | Dec(D, L); |
||
2536 | B := B xor R; |
||
2537 | end; |
||
2538 | R := B * K[3]; |
||
2539 | R := R shl 5 or R shr 27; |
||
2540 | B := B shr 13 or B shl 19; |
||
2541 | L := B + K[2]; |
||
2542 | Dec(D, L shl R or L shr (32 - R)); |
||
2543 | L := Mars_Data[L and $1FF] xor R; |
||
2544 | R := R shl 5 or R shr 27; |
||
2545 | L := L xor R; |
||
2546 | L := L shl R or L shr (32 - R); |
||
2547 | if I <= 1 then |
||
2548 | begin |
||
2549 | Dec(A, L); |
||
2550 | C := C xor R; |
||
2551 | end else |
||
2552 | begin |
||
2553 | Dec(C, L); |
||
2554 | A := A xor R; |
||
2555 | end; |
||
2556 | R := A * K[1]; |
||
2557 | R := R shl 5 or R shr 27; |
||
2558 | A := A shr 13 or A shl 19; |
||
2559 | L := A + K[0]; |
||
2560 | Dec(C, L shl R or L shr (32 - R)); |
||
2561 | L := Mars_Data[L and $1FF] xor R; |
||
2562 | R := R shl 5 or R shr 27; |
||
2563 | L := L xor R; |
||
2564 | L := L shl R or L shr (32 - R); |
||
2565 | if I <= 1 then |
||
2566 | begin |
||
2567 | Dec(D, L); |
||
2568 | B := B xor R; |
||
2569 | end else |
||
2570 | begin |
||
2571 | Dec(B, L); |
||
2572 | D := D xor R; |
||
2573 | end; |
||
2574 | Dec(PLongWord(K), 8); |
||
2575 | end; |
||
2576 | for I := 0 to 1 do |
||
2577 | begin |
||
2578 | D := D shl 24 or D shr 8; |
||
2579 | C := C xor Mars_Data[D shr 24 + 256]; |
||
2580 | Dec(B, Mars_Data[D shr 16 and $FF]); |
||
2581 | A := A - Mars_Data[D shr 8 and $FF + 256] xor Mars_Data[D and $FF]; |
||
2582 | C := C shl 24 or C shr 8; |
||
2583 | B := B xor Mars_Data[C shr 24 + 256]; |
||
2584 | Dec(A, Mars_Data[C shr 16 and $FF]); |
||
2585 | D := D - Mars_Data[C shr 8 and $FF + 256] xor Mars_Data[C and $FF]; |
||
2586 | Dec(B, C); |
||
2587 | B := B shl 24 or B shr 8; |
||
2588 | A := A xor Mars_Data[B shr 24 + 256]; |
||
2589 | Dec(D, Mars_Data[B shr 16 and $FF]); |
||
2590 | C := C - Mars_Data[B shr 8 and $FF + 256] xor Mars_Data[B and $FF]; |
||
2591 | Dec(A, D); |
||
2592 | A := A shl 24 or A shr 8; |
||
2593 | D := D xor Mars_Data[A shr 24 + 256]; |
||
2594 | Dec(C, Mars_Data[A shr 16 and $FF]); |
||
2595 | B := B - Mars_Data[A shr 8 and $FF + 256] xor Mars_Data[A and $FF]; |
||
2596 | end; |
||
2597 | PLongArray(Dest)[0] := A - K[4]; |
||
2598 | PLongArray(Dest)[1] := B - K[5]; |
||
2599 | PLongArray(Dest)[2] := C - K[6]; |
||
2600 | PLongArray(Dest)[3] := D - K[7]; |
||
2601 | end; |
||
2602 | |||
2603 | // .TCipher_RC4 |
||
2604 | class function TCipher_RC4.Context: TCipherContext; |
||
2605 | begin |
||
2606 | Result.KeySize := 256; |
||
2607 | Result.BlockSize := 1; |
||
2608 | Result.BufferSize := 16; |
||
2609 | Result.UserSize := 256 + 2; |
||
2610 | Result.UserSave := True; |
||
2611 | end; |
||
2612 | |||
2613 | procedure TCipher_RC4.DoInit(const Key; Size: Integer); |
||
2614 | var |
||
2615 | K: array[0..255] of Byte; |
||
2616 | D: PByteArray; |
||
2617 | I,J,T: Byte; |
||
2618 | begin |
||
2619 | D := FUser; |
||
2620 | for I := 0 to 255 do |
||
2621 | begin |
||
2622 | D[I] := I; |
||
2623 | if Size > 0 then |
||
2624 | K[I] := TByteArray(Key)[I mod Size]; |
||
2625 | end; |
||
2626 | J := 0; |
||
2627 | for I := 0 to 255 do |
||
2628 | begin |
||
2629 | J := J + D[I] + K[I]; |
||
2630 | T := D[I]; |
||
2631 | D[I] := D[J]; |
||
2632 | D[J] := T; |
||
2633 | end; |
||
2634 | D[256] := 0; |
||
2635 | D[257] := 0; |
||
2636 | ProtectBuffer(K, SizeOf(K)); |
||
2637 | end; |
||
2638 | |||
2639 | procedure TCipher_RC4.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
2640 | var |
||
2641 | D: PByteArray; |
||
2642 | S: Integer; |
||
2643 | T,I,J: Byte; |
||
2644 | begin |
||
2645 | D := FUser; |
||
2646 | I := D[256]; |
||
2647 | J := D[257]; |
||
2648 | for S := 0 to Size -1 do |
||
2649 | begin |
||
2650 | Inc(I); |
||
2651 | T := D[I]; |
||
2652 | Inc(J, T); |
||
2653 | D[I] := D[J]; |
||
2654 | D[J] := T; |
||
2655 | PByteArray(Dest)[S] := PByteArray(Source)[S] xor D[Byte(D[I] + T)]; |
||
2656 | end; |
||
2657 | D[256] := I; |
||
2658 | D[257] := J; |
||
2659 | end; |
||
2660 | |||
2661 | procedure TCipher_RC4.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
2662 | begin |
||
2663 | DoEncode(Source, Dest, Size); |
||
2664 | end; |
||
2665 | |||
2666 | // .TCipher_RC6 |
||
2667 | class function TCipher_RC6.Context: TCipherContext; |
||
2668 | begin |
||
2669 | Result.KeySize := 256; |
||
2670 | Result.BlockSize := 16; |
||
2671 | Result.BufferSize := 16; |
||
2672 | Result.UserSize := 272; |
||
2673 | Result.UserSave := False; |
||
2674 | end; |
||
2675 | |||
2676 | procedure TCipher_RC6.SetRounds(Value: Integer); |
||
2677 | begin |
||
2678 | if Value < 16 then Value := 16 else |
||
2679 | if Value > 24 then Value := 24; |
||
2680 | if Value <> FRounds then |
||
2681 | begin |
||
2682 | if not (FState in [csNew, csInitialized, csDone]) then Done; |
||
2683 | FRounds := Value; |
||
2684 | end; |
||
2685 | end; |
||
2686 | |||
2687 | procedure TCipher_RC6.DoInit(const Key; Size: Integer); |
||
2688 | var |
||
2689 | K: array[0..63] of LongWord; |
||
2690 | D: PLongArray; |
||
2691 | I,J,L,A,B,Z,T: LongWord; |
||
2692 | begin |
||
2693 | if FRounds = 0 then FRounds := 20 else |
||
2694 | if FRounds < 16 then FRounds := 16 else |
||
2695 | if FRounds > 24 then FRounds := 24; |
||
2696 | D := FUser; |
||
2697 | FillChar(K, SizeOf(K), 0); |
||
2698 | Move(Key, K, Size); |
||
2699 | L := Size shr 2; |
||
2700 | if Size and 3 <> 0 then Inc(L); |
||
2701 | if L <= 0 then L := 1; |
||
2702 | J := $B7E15163; |
||
2703 | for I := 0 to (FRounds + 2) * 2 do |
||
2704 | begin |
||
2705 | D[I] := J; |
||
2706 | Inc(J, $9E3779B9); |
||
2707 | end; |
||
2708 | if L > LongWord(FRounds + 2) * 2 then Z := L * 3 |
||
2709 | else Z := (FRounds + 2) * 6; |
||
2710 | I := 0; |
||
2711 | J := 0; |
||
2712 | A := 0; |
||
2713 | B := 0; |
||
2714 | for Z := Z downto 1 do |
||
2715 | begin |
||
2716 | A := A + B + D[I]; |
||
2717 | A := A shl 3 or A shr 29; |
||
2718 | D[I] := A; |
||
2719 | T := A + B; |
||
2720 | B := T + K[J]; |
||
2721 | B := B shl T or B shr (32 - T); |
||
2722 | K[J] := B; |
||
2723 | I := (I + 1) mod (LongWord(FRounds + 2) * 2); |
||
2724 | J := (J + 1) mod L; |
||
2725 | end; |
||
2726 | ProtectBuffer(K, SizeOf(K)); |
||
2727 | end; |
||
2728 | |||
2729 | procedure TCipher_RC6.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
2730 | {$IFDEF UseASM} |
||
2731 | asm |
||
2732 | PUSH EBX |
||
2733 | PUSH ESI |
||
2734 | PUSH EDI |
||
2735 | PUSH EBP |
||
2736 | PUSH ECX |
||
2737 | MOV EBP,[EAX].TCipher_RC6.FRounds // Rounds |
||
2738 | MOV ESI,[EAX].TCipher_RC6.FUser // Key |
||
2739 | MOV EAX,[EDX + 0] // A |
||
2740 | MOV EBX,[EDX + 4] // B |
||
2741 | MOV EDI,[EDX + 8] // C |
||
2742 | MOV EDX,[EDX + 12] // D |
||
2743 | ADD EBX,[ESI + 0] // Inc(B, K[0]) |
||
2744 | ADD EDX,[ESI + 4] // Inc(D, K[1]) |
||
2745 | ADD ESI,8 // Inc(PInteger(K), 2) |
||
2746 | @@1: LEA ECX,[EBX * 2 +1] // ECX := B * 2 +1 |
||
2747 | IMUL ECX,EBX // ECX := ECX * B |
||
2748 | ROL ECX,5 // T := ROL(B * (B * 2 +1), 5) |
||
2749 | PUSH ECX // save T |
||
2750 | XOR EAX,ECX // A := A xor T |
||
2751 | LEA ECX,[EDX * 2 +1] // ECX := D * 2 +1 |
||
2752 | IMUL ECX,EDX // ECX := ECX * D |
||
2753 | ROL ECX,5 // U := ROL(D * (D * 2 +1), 5) |
||
2754 | XOR EDI,ECX // C := C xor U |
||
2755 | ROL EAX,CL // A := ROL(A xor T, U) |
||
2756 | POP ECX // restore T |
||
2757 | ADD EAX,[ESI + 0] // Inc(A, K[0]) |
||
2758 | ROL EDI,CL // C := ROL(C xor U, T) |
||
2759 | MOV ECX,EAX // T := A |
||
2760 | ADD EDI,[ESI + 4] // Inc(C, K[1]) |
||
2761 | MOV EAX,EBX // A := B |
||
2762 | MOV EBX,EDI // B := C |
||
2763 | MOV EDI,EDX // C := D |
||
2764 | DEC EBP |
||
2765 | MOV EDX,ECX // D := T; |
||
2766 | LEA ESI,[ESI + 8] // Inc(PInteger(K), 2) |
||
2767 | JNZ @@1 |
||
2768 | ADD EAX,[ESI + 0] // Inc(A, K[0]) |
||
2769 | ADD EDI,[ESI + 4] // Inc(C, K[1]) |
||
2770 | POP ECX |
||
2771 | MOV [ECX + 0],EAX // A |
||
2772 | MOV [ECX + 4],EBX // B |
||
2773 | MOV [ECX + 8],EDI // C |
||
2774 | MOV [ECX + 12],EDX // D |
||
2775 | POP EBP |
||
2776 | POP EDI |
||
2777 | POP ESI |
||
2778 | POP EBX |
||
2779 | end; |
||
2780 | {$ELSE} |
||
2781 | var |
||
2782 | K: PLongArray; |
||
2783 | I,T,U,A,B,C,D: LongWord; |
||
2784 | begin |
||
2785 | Assert(Size = Context.BlockSize); |
||
2786 | |||
2787 | K := FUser; |
||
2788 | A := PLongArray(Source)[0]; |
||
2789 | B := PLongArray(Source)[1] + K[0]; |
||
2790 | C := PLongArray(Source)[2]; |
||
2791 | D := PLongArray(Source)[3] + K[1]; |
||
2792 | for I := 1 to FRounds do |
||
2793 | begin |
||
2794 | K := @K[2]; |
||
2795 | T := B * (B + B +1); |
||
2796 | T := T shl 5 or T shr 27; |
||
2797 | U := D * (D + D +1); |
||
2798 | U := U shl 5 or U shr 27; |
||
2799 | A := A xor T; |
||
2800 | A := A shl U or A shr (32 - U) + K[0]; |
||
2801 | C := C xor U; |
||
2802 | C := C shl T or C shr (32 - T) + K[1]; |
||
2803 | T := A; A := B; B := C; C := D; D := T; |
||
2804 | end; |
||
2805 | PLongArray(Dest)[0] := A + K[2]; |
||
2806 | PLongArray(Dest)[1] := B; |
||
2807 | PLongArray(Dest)[2] := C + K[3]; |
||
2808 | PLongArray(Dest)[3] := D; |
||
2809 | end; |
||
2810 | {$ENDIF} |
||
2811 | |||
2812 | procedure TCipher_RC6.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
2813 | {$IFDEF UseASM} |
||
2814 | asm |
||
2815 | PUSH EBX |
||
2816 | PUSH ESI |
||
2817 | PUSH EDI |
||
2818 | PUSH EBP |
||
2819 | PUSH ECX |
||
2820 | MOV EBP,[EAX].TCipher_RC6.FRounds // Rounds |
||
2821 | MOV ESI,[EAX].TCipher_RC6.FUser // Key |
||
2822 | LEA ESI,[ESI + EBP * 8] // Key[FRounds * 2] |
||
2823 | MOV EAX,[EDX + 0] // A |
||
2824 | MOV EBX,[EDX + 4] // B |
||
2825 | MOV EDI,[EDX + 8] // C |
||
2826 | MOV EDX,[EDX + 12] // D |
||
2827 | SUB EDI,[ESI + 12] // Dec(C, K[3]) |
||
2828 | SUB EAX,[ESI + 8] // Dec(A, K[2]) |
||
2829 | @@1: MOV ECX,EAX // T := A |
||
2830 | SUB EDX,[ESI + 0] // Dec(A, K[0]) |
||
2831 | MOV EAX,EDX // A := D |
||
2832 | MOV EDX,EDI // D := C |
||
2833 | SUB EBX,[ESI + 4] // Dec(C, K[1]) |
||
2834 | MOV EDI,EBX // C := B |
||
2835 | MOV EBX,ECX // B := T; |
||
2836 | LEA ECX,[EDX * 2 +1] // ECX := D * 2 +1 |
||
2837 | IMUL ECX,EDX // ECX := ECX * D |
||
2838 | ROL ECX,5 // U := ROL(D * (D * 2 +1), 5) |
||
2839 | PUSH ECX // save U |
||
2840 | ROR EAX,CL // A := ROR(A - K[0], U) |
||
2841 | LEA ECX,[EBX * 2 +1] // ECX := B * 2 +1 |
||
2842 | IMUL ECX,EBX // ECX := ECX * B |
||
2843 | ROL ECX,5 // T := ROL(B * (B * 2 +1), 5) |
||
2844 | XOR EAX,ECX // A := A xor T |
||
2845 | ROR EDI,CL // C := ROR(C - K[1], T) |
||
2846 | POP ECX // restore U |
||
2847 | XOR EDI,ECX // C := C xor U |
||
2848 | DEC EBP |
||
2849 | LEA ESI,[ESI - 8] // Dec(PInteger(K), 2) |
||
2850 | JNZ @@1 |
||
2851 | SUB EBX,[ESI + 0] // Dec(B, K[0]) |
||
2852 | SUB EDX,[ESI + 4] // Inc(D, K[1]) |
||
2853 | POP ECX |
||
2854 | MOV [ECX + 0],EAX // A |
||
2855 | MOV [ECX + 4],EBX // B |
||
2856 | MOV [ECX + 8],EDI // C |
||
2857 | MOV [ECX + 12],EDX // D |
||
2858 | POP EBP |
||
2859 | POP EDI |
||
2860 | POP ESI |
||
2861 | POP EBX |
||
2862 | end; |
||
2863 | {$ELSE} |
||
2864 | var |
||
2865 | I,U,T,A,B,C,D: LongWord; |
||
2866 | K: PLongArray; |
||
2867 | begin |
||
2868 | Assert(Size = Context.BlockSize); |
||
2869 | |||
2870 | K := @PLongArray(FUser)[FRounds * 2]; |
||
2871 | A := PLongArray(Source)[0] - K[2]; |
||
2872 | B := PLongArray(Source)[1]; |
||
2873 | C := PLongArray(Source)[2] - K[3]; |
||
2874 | D := PLongArray(Source)[3]; |
||
2875 | for I := 1 to FRounds do |
||
2876 | begin |
||
2877 | T := A; A := D; D := C; C := B; B := T; |
||
2878 | U := D * (D + D +1); |
||
2879 | U := U shl 5 or U shr 27; |
||
2880 | T := B * (B + B +1); |
||
2881 | T := T shl 5 or T shr 27; |
||
2882 | C := C - K[1]; |
||
2883 | C := C shr T or C shl (32 - T) xor U; |
||
2884 | A := A - K[0]; |
||
2885 | A := A shr U or A shl (32 - U) xor T; |
||
2886 | Dec(PLongWord(K), 2); |
||
2887 | end; |
||
2888 | PLongArray(Dest)[0] := A; |
||
2889 | PLongArray(Dest)[1] := B - K[0]; |
||
2890 | PLongArray(Dest)[2] := C; |
||
2891 | PLongArray(Dest)[3] := D - K[1]; |
||
2892 | end; |
||
2893 | {$ENDIF} |
||
2894 | |||
2895 | // .TCipher_Rijndael |
||
2896 | const |
||
2897 | {don't change this} |
||
2898 | Rijndael_Blocks = 4; |
||
2899 | Rijndael_Rounds = 14; |
||
2900 | |||
2901 | class function TCipher_Rijndael.Context: TCipherContext; |
||
2902 | begin |
||
2903 | Result.KeySize := 32; |
||
2904 | Result.BlockSize := Rijndael_Blocks * 4; |
||
2905 | Result.BufferSize := Rijndael_Blocks * 4; |
||
2906 | Result.UserSize := (Rijndael_Rounds + 1) * Rijndael_Blocks * SizeOf(LongWord) * 2; |
||
2907 | Result.UserSave := False; |
||
2908 | end; |
||
2909 | |||
2910 | procedure TCipher_Rijndael.DoInit(const Key; Size: Integer); |
||
2911 | { old Rijndael keyshedulling |
||
2912 | |||
2913 | procedure BuildEncodeKey; |
||
2914 | const |
||
2915 | RND_Data: array[0..29] of Byte = ( |
||
2916 | $01,$02,$04,$08,$10,$20,$40,$80,$1B,$36,$6C,$D8,$AB,$4D,$9A, |
||
2917 | $2F,$5E,$BC,$63,$C6,$97,$35,$6A,$D4,$B3,$7D,$FA,$EF,$C5,$91); |
||
2918 | var |
||
2919 | T,R: Integer; |
||
2920 | |||
2921 | procedure NextRounds; |
||
2922 | var |
||
2923 | J: Integer; |
||
2924 | begin |
||
2925 | J := 0; |
||
2926 | while (J < FRounds -6) and (R <= FRounds) do |
||
2927 | begin |
||
2928 | while (J < FRounds -6) and (T < Rijndael_Blocks) do |
||
2929 | begin |
||
2930 | PLongArray(FUser)[R * Rijndael_Blocks + T] := K[J]; |
||
2931 | Inc(J); |
||
2932 | Inc(T); |
||
2933 | end; |
||
2934 | if T = Rijndael_Blocks then |
||
2935 | begin |
||
2936 | T := 0; |
||
2937 | Inc(R); |
||
2938 | end; |
||
2939 | end; |
||
2940 | end; |
||
2941 | |||
2942 | var |
||
2943 | RND: PByte; |
||
2944 | B: PByte; |
||
2945 | I: Integer; |
||
2946 | begin |
||
2947 | R := 0; |
||
2948 | T := 0; |
||
2949 | RND := @RND_Data; |
||
2950 | NextRounds; |
||
2951 | while R <= FRounds do |
||
2952 | begin |
||
2953 | B := @K; |
||
2954 | B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr 8 and $FF] xor RND^; Inc(B); |
||
2955 | B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr 16 and $FF]; Inc(B); |
||
2956 | B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr 24]; Inc(B); |
||
2957 | B^ := B^ xor Rijndael_S[0, K[FRounds -7] and $FF]; |
||
2958 | Inc(RND); |
||
2959 | if FRounds = 14 then |
||
2960 | begin |
||
2961 | for I := 1 to 7 do K[I] := K[I] xor K[I -1]; |
||
2962 | B := @K[4]; |
||
2963 | B^ := B^ xor Rijndael_S[0, K[3] and $FF]; Inc(B); |
||
2964 | B^ := B^ xor Rijndael_S[0, K[3] shr 8 and $FF]; Inc(B); |
||
2965 | B^ := B^ xor Rijndael_S[0, K[3] shr 16 and $FF]; Inc(B); |
||
2966 | B^ := B^ xor Rijndael_S[0, K[3] shr 24]; |
||
2967 | for I := 5 to 7 do K[I] := K[I] xor K[I -1]; |
||
2968 | end else |
||
2969 | for I := 1 to FRounds -7 do K[I] := K[I] xor K[I -1]; |
||
2970 | NextRounds; |
||
2971 | end; |
||
2972 | end; |
||
2973 | |||
2974 | procedure BuildDecodeKey; |
||
2975 | var |
||
2976 | I: Integer; |
||
2977 | D: PLongWord; |
||
2978 | begin |
||
2979 | D := Pointer(PChar(FUser) + FUserSize shr 1); |
||
2980 | Move(FUser^, D^, FUserSize shr 1); |
||
2981 | Inc(D, 4); |
||
2982 | for I := 0 to FRounds * 4 - 5 do |
||
2983 | begin |
||
2984 | D^ := Rijndael_Key[D^ and $FF] xor |
||
2985 | (Rijndael_Key[D^ shr 8 and $FF] shl 8 or Rijndael_Key[D^ shr 8 and $FF] shr 24) xor |
||
2986 | (Rijndael_Key[D^ shr 16 and $FF] shl 16 or Rijndael_Key[D^ shr 16 and $FF] shr 16) xor |
||
2987 | (Rijndael_Key[D^ shr 24] shl 24 or Rijndael_Key[D^ shr 24] shr 8); |
||
2988 | Inc(D); |
||
2989 | end; |
||
2990 | end; } |
||
2991 | |||
2992 | // new AES conform Keyshedulling |
||
2993 | |||
2994 | procedure BuildEncodeKey; |
||
2995 | const |
||
2996 | RCon: array[0..9] of LongWord = ($01,$02,$04,$08,$10,$20,$40,$80,$1b,$36); |
||
2997 | var |
||
2998 | I: Integer; |
||
2999 | T: LongWord; |
||
3000 | P: PLongArray; |
||
3001 | begin |
||
3002 | P := FUser; |
||
3003 | if Size <= 16 then |
||
3004 | begin |
||
3005 | for I := 0 to 9 do |
||
3006 | begin |
||
3007 | T := P[3]; |
||
3008 | P[4] := Rijndael_S[0, T shr 8 and $FF] xor |
||
3009 | Rijndael_S[0, T shr 16 and $FF] shl 8 xor |
||
3010 | Rijndael_S[0, T shr 24 ] shl 16 xor |
||
3011 | Rijndael_S[0, T and $FF] shl 24 xor P[0] xor RCon[I]; |
||
3012 | P[5] := P[1] xor P[4]; |
||
3013 | P[6] := P[2] xor P[5]; |
||
3014 | P[7] := P[3] xor P[6]; |
||
3015 | P := @P[4]; |
||
3016 | end; |
||
3017 | end else |
||
3018 | if Size <= 24 then |
||
3019 | begin |
||
3020 | for I := 0 to 7 do |
||
3021 | begin |
||
3022 | T := P[5]; |
||
3023 | P[6] := Rijndael_S[0, T shr 8 and $FF] xor |
||
3024 | Rijndael_S[0, T shr 16 and $FF] shl 8 xor |
||
3025 | Rijndael_S[0, T shr 24 ] shl 16 xor |
||
3026 | Rijndael_S[0, T and $FF] shl 24 xor P[0] xor RCon[I]; |
||
3027 | P[7] := P[1] xor P[6]; |
||
3028 | P[8] := P[2] xor P[7]; |
||
3029 | P[9] := P[3] xor P[8]; |
||
3030 | if I = 7 then Break; |
||
3031 | P[10] := P[4] xor P[9]; |
||
3032 | P[11] := P[5] xor P[10]; |
||
3033 | P := @P[6]; |
||
3034 | end; |
||
3035 | end else |
||
3036 | begin |
||
3037 | for I :=0 to 6 do |
||
3038 | begin |
||
3039 | T := P[7]; |
||
3040 | P[8] := Rijndael_S[0, T shr 8 and $FF] xor |
||
3041 | Rijndael_S[0, T shr 16 and $FF] shl 8 xor |
||
3042 | Rijndael_S[0, T shr 24 ] shl 16 xor |
||
3043 | Rijndael_S[0, T and $FF] shl 24 xor P[0] xor RCon[I]; |
||
3044 | P[9] := P[1] xor P[8]; |
||
3045 | P[10] := P[2] xor P[9]; |
||
3046 | P[11] := P[3] xor P[10]; |
||
3047 | if I = 6 then Break; |
||
3048 | T := P[11]; |
||
3049 | P[12] := Rijndael_S[0, T and $FF] xor |
||
3050 | Rijndael_S[0, T shr 8 and $FF] shl 8 xor |
||
3051 | Rijndael_S[0, T shr 16 and $FF] shl 16 xor |
||
3052 | Rijndael_S[0, T shr 24 ] shl 24 xor P[4]; |
||
3053 | P[13] := P[5] xor P[12]; |
||
3054 | P[14] := P[6] xor P[13]; |
||
3055 | P[15] := P[7] xor P[14]; |
||
3056 | P := @P[8]; |
||
3057 | end; |
||
3058 | end; |
||
3059 | end; |
||
3060 | |||
3061 | |||
3062 | procedure BuildDecodeKey; |
||
3063 | var |
||
3064 | P: PLongWord; |
||
3065 | I: Integer; |
||
3066 | begin |
||
3067 | P := Pointer(PChar(FUser) + FUserSize shr 1); |
||
3068 | Move(FUser^, P^, FUserSize shr 1); |
||
3069 | Inc(P, 4); |
||
3070 | for I := 0 to FRounds * 4 -5 do |
||
3071 | begin |
||
3072 | P^ := Rijndael_T[4, Rijndael_S[0, P^ and $FF]] xor |
||
3073 | Rijndael_T[5, Rijndael_S[0, P^ shr 8 and $FF]] xor |
||
3074 | Rijndael_T[6, Rijndael_S[0, P^ shr 16 and $FF]] xor |
||
3075 | Rijndael_T[7, Rijndael_S[0, P^ shr 24 ]]; |
||
3076 | Inc(P); |
||
3077 | end; |
||
3078 | end; |
||
3079 | |||
3080 | |||
3081 | begin |
||
3082 | if Size <= 16 then FRounds := 10 else |
||
3083 | if Size <= 24 then FRounds := 12 |
||
3084 | else FRounds := 14; |
||
3085 | FillChar(FUser^, 32, 0); |
||
3086 | Move(Key, FUser^, Size); |
||
3087 | BuildEncodeKey; |
||
3088 | BuildDecodeKey; |
||
3089 | end; |
||
3090 | |||
3091 | procedure TCipher_Rijndael.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3092 | var |
||
3093 | P: PLongArray; |
||
3094 | I: Integer; |
||
3095 | A2,B2,C2,D2: LongWord; |
||
3096 | A1,B1,C1,D1: LongWord; |
||
3097 | begin |
||
3098 | Assert(Size = Context.BlockSize); |
||
3099 | P := FUser; |
||
3100 | A1 := PLongArray(Source)[0]; |
||
3101 | B1 := PLongArray(Source)[1]; |
||
3102 | C1 := PLongArray(Source)[2]; |
||
3103 | D1 := PLongArray(Source)[3]; |
||
3104 | for I := 2 to FRounds do |
||
3105 | begin |
||
3106 | A2 := A1 xor P[0]; |
||
3107 | B2 := B1 xor P[1]; |
||
3108 | C2 := C1 xor P[2]; |
||
3109 | D2 := D1 xor P[3]; |
||
3110 | |||
3111 | A1 := Rijndael_T[0, A2 and $FF] xor |
||
3112 | Rijndael_T[1, B2 shr 8 and $FF] xor |
||
3113 | Rijndael_T[2, C2 shr 16 and $FF] xor |
||
3114 | Rijndael_T[3, D2 shr 24 ]; |
||
3115 | B1 := Rijndael_T[0, B2 and $FF] xor |
||
3116 | Rijndael_T[1, C2 shr 8 and $FF] xor |
||
3117 | Rijndael_T[2, D2 shr 16 and $FF] xor |
||
3118 | Rijndael_T[3, A2 shr 24 ]; |
||
3119 | C1 := Rijndael_T[0, C2 and $FF] xor |
||
3120 | Rijndael_T[1, D2 shr 8 and $FF] xor |
||
3121 | Rijndael_T[2, A2 shr 16 and $FF] xor |
||
3122 | Rijndael_T[3, B2 shr 24 ]; |
||
3123 | D1 := Rijndael_T[0, D2 and $FF] xor |
||
3124 | Rijndael_T[1, A2 shr 8 and $FF] xor |
||
3125 | Rijndael_T[2, B2 shr 16 and $FF] xor |
||
3126 | Rijndael_T[3, C2 shr 24 ]; |
||
3127 | |||
3128 | P := @P[4]; |
||
3129 | end; |
||
3130 | |||
3131 | A2 := A1 xor P[0]; |
||
3132 | B2 := B1 xor P[1]; |
||
3133 | C2 := C1 xor P[2]; |
||
3134 | D2 := D1 xor P[3]; |
||
3135 | |||
3136 | PLongArray(Dest)[0] := (Rijndael_S[0, A2 and $FF] or |
||
3137 | Rijndael_S[0, B2 shr 8 and $FF] shl 8 or |
||
3138 | Rijndael_S[0, C2 shr 16 and $FF] shl 16 or |
||
3139 | Rijndael_S[0, D2 shr 24 ] shl 24) xor P[4]; |
||
3140 | PLongArray(Dest)[1] := (Rijndael_S[0, B2 and $FF] or |
||
3141 | Rijndael_S[0, C2 shr 8 and $FF] shl 8 or |
||
3142 | Rijndael_S[0, D2 shr 16 and $FF] shl 16 or |
||
3143 | Rijndael_S[0, A2 shr 24 ] shl 24) xor P[5]; |
||
3144 | PLongArray(Dest)[2] := (Rijndael_S[0, C2 and $FF] or |
||
3145 | Rijndael_S[0, D2 shr 8 and $FF] shl 8 or |
||
3146 | Rijndael_S[0, A2 shr 16 and $FF] shl 16 or |
||
3147 | Rijndael_S[0, B2 shr 24 ] shl 24) xor P[6]; |
||
3148 | PLongArray(Dest)[3] := (Rijndael_S[0, D2 and $FF] or |
||
3149 | Rijndael_S[0, A2 shr 8 and $FF] shl 8 or |
||
3150 | Rijndael_S[0, B2 shr 16 and $FF] shl 16 or |
||
3151 | Rijndael_S[0, C2 shr 24 ] shl 24) xor P[7]; |
||
3152 | end; |
||
3153 | |||
3154 | procedure TCipher_Rijndael.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3155 | var |
||
3156 | P: PLongArray; |
||
3157 | I: Integer; |
||
3158 | A2,B2,C2,D2: LongWord; |
||
3159 | A1,B1,C1,D1: LongWord; |
||
3160 | begin |
||
3161 | Assert(Size = Context.BlockSize); |
||
3162 | |||
3163 | P := Pointer(PChar(FUser) + FUserSize shr 1 + FRounds * 16); |
||
3164 | A1 := PLongArray(Source)[0]; |
||
3165 | B1 := PLongArray(Source)[1]; |
||
3166 | C1 := PLongArray(Source)[2]; |
||
3167 | D1 := PLongArray(Source)[3]; |
||
3168 | |||
3169 | for I := 2 to FRounds do |
||
3170 | begin |
||
3171 | A2 := A1 xor P[0]; |
||
3172 | B2 := B1 xor P[1]; |
||
3173 | C2 := C1 xor P[2]; |
||
3174 | D2 := D1 xor P[3]; |
||
3175 | |||
3176 | A1 := Rijndael_T[4, A2 and $FF] xor |
||
3177 | Rijndael_T[5, D2 shr 8 and $FF] xor |
||
3178 | Rijndael_T[6, C2 shr 16 and $FF] xor |
||
3179 | Rijndael_T[7, B2 shr 24 ]; |
||
3180 | B1 := Rijndael_T[4, B2 and $FF] xor |
||
3181 | Rijndael_T[5, A2 shr 8 and $FF] xor |
||
3182 | Rijndael_T[6, D2 shr 16 and $FF] xor |
||
3183 | Rijndael_T[7, C2 shr 24 ]; |
||
3184 | C1 := Rijndael_T[4, C2 and $FF] xor |
||
3185 | Rijndael_T[5, B2 shr 8 and $FF] xor |
||
3186 | Rijndael_T[6, A2 shr 16 and $FF] xor |
||
3187 | Rijndael_T[7, D2 shr 24 ]; |
||
3188 | D1 := Rijndael_T[4, D2 and $FF] xor |
||
3189 | Rijndael_T[5, C2 shr 8 and $FF] xor |
||
3190 | Rijndael_T[6, B2 shr 16 and $FF] xor |
||
3191 | Rijndael_T[7, A2 shr 24 ]; |
||
3192 | |||
3193 | Dec(PLongWord(P), 4); |
||
3194 | end; |
||
3195 | |||
3196 | A2 := A1 xor P[0]; |
||
3197 | B2 := B1 xor P[1]; |
||
3198 | C2 := C1 xor P[2]; |
||
3199 | D2 := D1 xor P[3]; |
||
3200 | |||
3201 | Dec(PLongWord(P), 4); |
||
3202 | |||
3203 | PLongArray(Dest)[0] := (Rijndael_S[1, A2 and $FF] or |
||
3204 | Rijndael_S[1, D2 shr 8 and $FF] shl 8 or |
||
3205 | Rijndael_S[1, C2 shr 16 and $FF] shl 16 or |
||
3206 | Rijndael_S[1, B2 shr 24] shl 24) xor P[0]; |
||
3207 | PLongArray(Dest)[1] := (Rijndael_S[1, B2 and $FF] or |
||
3208 | Rijndael_S[1, A2 shr 8 and $FF] shl 8 or |
||
3209 | Rijndael_S[1, D2 shr 16 and $FF] shl 16 or |
||
3210 | Rijndael_S[1, C2 shr 24] shl 24) xor P[1]; |
||
3211 | PLongArray(Dest)[2] := (Rijndael_S[1, C2 and $FF] or |
||
3212 | Rijndael_S[1, B2 shr 8 and $FF] shl 8 or |
||
3213 | Rijndael_S[1, A2 shr 16 and $FF] shl 16 or |
||
3214 | Rijndael_S[1, D2 shr 24] shl 24) xor P[2]; |
||
3215 | PLongArray(Dest)[3] := (Rijndael_S[1, D2 and $FF] or |
||
3216 | Rijndael_S[1, C2 shr 8 and $FF] shl 8 or |
||
3217 | Rijndael_S[1, B2 shr 16 and $FF] shl 16 or |
||
3218 | Rijndael_S[1, A2 shr 24] shl 24) xor P[3]; |
||
3219 | end; |
||
3220 | |||
3221 | // .TCipher_Square |
||
3222 | class function TCipher_Square.Context: TCipherContext; |
||
3223 | begin |
||
3224 | Result.KeySize := 16; |
||
3225 | Result.BlockSize := 16; |
||
3226 | Result.BufferSize := 16; |
||
3227 | Result.UserSize := 9 * 4 * 2 * SizeOf(LongWord); |
||
3228 | Result.UserSave := False; |
||
3229 | end; |
||
3230 | |||
3231 | procedure TCipher_Square.DoInit(const Key; Size: Integer); |
||
3232 | type |
||
3233 | PSquare_Key = ^TSquare_Key; |
||
3234 | TSquare_Key = array[0..8, 0..3] of LongWord; |
||
3235 | var |
||
3236 | E,D: PSquare_Key; |
||
3237 | S,T,R: LongWord; |
||
3238 | I,J: Integer; |
||
3239 | begin |
||
3240 | E := FUser; |
||
3241 | D := FUser; Inc(D); |
||
3242 | Move(Key, E^, Size); |
||
3243 | for I := 1 to 8 do |
||
3244 | begin |
||
3245 | T := E[I -1, 3]; |
||
3246 | T := T shr 8 or T shl 24; |
||
3247 | E[I, 0] := E[I -1, 0] xor T xor 1 shl (I - 1); |
||
3248 | E[I, 1] := E[I -1, 1] xor E[I, 0]; |
||
3249 | E[I, 2] := E[I -1, 2] xor E[I, 1]; |
||
3250 | E[I, 3] := E[I -1, 3] xor E[I, 2]; |
||
3251 | |||
3252 | D[8 -I, 0] := E[I, 0]; |
||
3253 | D[8 -I, 1] := E[I, 1]; |
||
3254 | D[8 -I, 2] := E[I, 2]; |
||
3255 | D[8 -I, 3] := E[I, 3]; |
||
3256 | |||
3257 | for J := 0 to 3 do |
||
3258 | begin |
||
3259 | R := E[I -1, J]; |
||
3260 | S := Square_PHI[R and $FF]; |
||
3261 | T := Square_PHI[R shr 8 and $FF]; |
||
3262 | T := T shl 8 or T shr 24; |
||
3263 | S := S xor T; |
||
3264 | T := Square_PHI[R shr 16 and $FF]; |
||
3265 | T := T shl 16 or T shr 16; |
||
3266 | S := S xor T; |
||
3267 | T := Square_PHI[R shr 24]; |
||
3268 | T := T shl 24 or T shr 8; |
||
3269 | S := S xor T; |
||
3270 | E[I -1, J] := S; |
||
3271 | end; |
||
3272 | end; |
||
3273 | D[8] := E[0]; |
||
3274 | end; |
||
3275 | |||
3276 | procedure TCipher_Square.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3277 | var |
||
3278 | Key: PLongArray; |
||
3279 | A,B,C,D: LongWord; |
||
3280 | AA,BB,CC: LongWord; |
||
3281 | I: Integer; |
||
3282 | begin |
||
3283 | Key := FUser; |
||
3284 | A := PLongArray(Source)[0] xor Key[0]; |
||
3285 | B := PLongArray(Source)[1] xor Key[1]; |
||
3286 | C := PLongArray(Source)[2] xor Key[2]; |
||
3287 | D := PLongArray(Source)[3] xor Key[3]; |
||
3288 | Key := @Key[4]; |
||
3289 | for I := 0 to 6 do |
||
3290 | begin |
||
3291 | AA := Square_TE[0, A and $FF] xor |
||
3292 | Square_TE[1, B and $FF] xor |
||
3293 | Square_TE[2, C and $FF] xor |
||
3294 | Square_TE[3, D and $FF] xor Key[0]; |
||
3295 | BB := Square_TE[0, A shr 8 and $FF] xor |
||
3296 | Square_TE[1, B shr 8 and $FF] xor |
||
3297 | Square_TE[2, C shr 8 and $FF] xor |
||
3298 | Square_TE[3, D shr 8 and $FF] xor Key[1]; |
||
3299 | CC := Square_TE[0, A shr 16 and $FF] xor |
||
3300 | Square_TE[1, B shr 16 and $FF] xor |
||
3301 | Square_TE[2, C shr 16 and $FF] xor |
||
3302 | Square_TE[3, D shr 16 and $FF] xor Key[2]; |
||
3303 | D := Square_TE[0, A shr 24 ] xor |
||
3304 | Square_TE[1, B shr 24 ] xor |
||
3305 | Square_TE[2, C shr 24 ] xor |
||
3306 | Square_TE[3, D shr 24 ] xor Key[3]; |
||
3307 | |||
3308 | A := AA; B := BB; C := CC; |
||
3309 | |||
3310 | Key := @Key[4]; |
||
3311 | end; |
||
3312 | |||
3313 | PLongArray(Dest)[0] := LongWord(Square_SE[A and $FF]) xor |
||
3314 | LongWord(Square_SE[B and $FF]) shl 8 xor |
||
3315 | LongWord(Square_SE[C and $FF]) shl 16 xor |
||
3316 | LongWord(Square_SE[D and $FF]) shl 24 xor Key[0]; |
||
3317 | PLongArray(Dest)[1] := LongWord(Square_SE[A shr 8 and $FF]) xor |
||
3318 | LongWord(Square_SE[B shr 8 and $FF]) shl 8 xor |
||
3319 | LongWord(Square_SE[C shr 8 and $FF]) shl 16 xor |
||
3320 | LongWord(Square_SE[D shr 8 and $FF]) shl 24 xor Key[1]; |
||
3321 | PLongArray(Dest)[2] := LongWord(Square_SE[A shr 16 and $FF]) xor |
||
3322 | LongWord(Square_SE[B shr 16 and $FF]) shl 8 xor |
||
3323 | LongWord(Square_SE[C shr 16 and $FF]) shl 16 xor |
||
3324 | LongWord(Square_SE[D shr 16 and $FF]) shl 24 xor Key[2]; |
||
3325 | PLongArray(Dest)[3] := LongWord(Square_SE[A shr 24 ]) xor |
||
3326 | LongWord(Square_SE[B shr 24 ]) shl 8 xor |
||
3327 | LongWord(Square_SE[C shr 24 ]) shl 16 xor |
||
3328 | LongWord(Square_SE[D shr 24 ]) shl 24 xor Key[3]; |
||
3329 | end; |
||
3330 | |||
3331 | procedure TCipher_Square.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3332 | var |
||
3333 | Key: PLongArray; |
||
3334 | A,B,C,D: LongWord; |
||
3335 | AA,BB,CC: LongWord; |
||
3336 | I: Integer; |
||
3337 | begin |
||
3338 | Key := @PLongArray(FUser)[9 * 4]; |
||
3339 | A := PLongArray(Source)[0] xor Key[0]; |
||
3340 | B := PLongArray(Source)[1] xor Key[1]; |
||
3341 | C := PLongArray(Source)[2] xor Key[2]; |
||
3342 | D := PLongArray(Source)[3] xor Key[3]; |
||
3343 | Key := @Key[4]; |
||
3344 | for I := 0 to 6 do |
||
3345 | begin |
||
3346 | AA := Square_TD[0, A and $FF] xor |
||
3347 | Square_TD[1, B and $FF] xor |
||
3348 | Square_TD[2, C and $FF] xor |
||
3349 | Square_TD[3, D and $FF] xor Key[0]; |
||
3350 | BB := Square_TD[0, A shr 8 and $FF] xor |
||
3351 | Square_TD[1, B shr 8 and $FF] xor |
||
3352 | Square_TD[2, C shr 8 and $FF] xor |
||
3353 | Square_TD[3, D shr 8 and $FF] xor Key[1]; |
||
3354 | CC := Square_TD[0, A shr 16 and $FF] xor |
||
3355 | Square_TD[1, B shr 16 and $FF] xor |
||
3356 | Square_TD[2, C shr 16 and $FF] xor |
||
3357 | Square_TD[3, D shr 16 and $FF] xor Key[2]; |
||
3358 | D := Square_TD[0, A shr 24 ] xor |
||
3359 | Square_TD[1, B shr 24 ] xor |
||
3360 | Square_TD[2, C shr 24 ] xor |
||
3361 | Square_TD[3, D shr 24 ] xor Key[3]; |
||
3362 | |||
3363 | A := AA; B := BB; C := CC; |
||
3364 | Key := @Key[4]; |
||
3365 | end; |
||
3366 | |||
3367 | PLongArray(Dest)[0] := LongWord(Square_SD[A and $FF]) xor |
||
3368 | LongWord(Square_SD[B and $FF]) shl 8 xor |
||
3369 | LongWord(Square_SD[C and $FF]) shl 16 xor |
||
3370 | LongWord(Square_SD[D and $FF]) shl 24 xor Key[0]; |
||
3371 | PLongArray(Dest)[1] := LongWord(Square_SD[A shr 8 and $FF]) xor |
||
3372 | LongWord(Square_SD[B shr 8 and $FF]) shl 8 xor |
||
3373 | LongWord(Square_SD[C shr 8 and $FF]) shl 16 xor |
||
3374 | LongWord(Square_SD[D shr 8 and $FF]) shl 24 xor Key[1]; |
||
3375 | PLongArray(Dest)[2] := LongWord(Square_SD[A shr 16 and $FF]) xor |
||
3376 | LongWord(Square_SD[B shr 16 and $FF]) shl 8 xor |
||
3377 | LongWord(Square_SD[C shr 16 and $FF]) shl 16 xor |
||
3378 | LongWord(Square_SD[D shr 16 and $FF]) shl 24 xor Key[2]; |
||
3379 | PLongArray(Dest)[3] := LongWord(Square_SD[A shr 24 ]) xor |
||
3380 | LongWord(Square_SD[B shr 24 ]) shl 8 xor |
||
3381 | LongWord(Square_SD[C shr 24 ]) shl 16 xor |
||
3382 | LongWord(Square_SD[D shr 24 ]) shl 24 xor Key[3]; |
||
3383 | end; |
||
3384 | |||
3385 | // .TCipher_SCOP |
||
3386 | class function TCipher_SCOP.Context: TCipherContext; |
||
3387 | begin |
||
3388 | Result.KeySize := 48; |
||
3389 | Result.BlockSize := 4; |
||
3390 | Result.BufferSize := 32; |
||
3391 | Result.UserSize := 384 * 4 + 3 * SizeOf(LongWord); |
||
3392 | Result.UserSave := True; |
||
3393 | end; |
||
3394 | |||
3395 | procedure TCipher_SCOP.DoInit(const Key; Size: Integer); |
||
3396 | var |
||
3397 | Init_State: packed record |
||
3398 | Coef: array[0..7, 0..3] of Byte; |
||
3399 | X: array[0..3] of LongWord; |
||
3400 | end; |
||
3401 | |||
3402 | procedure ExpandKey; |
||
3403 | var |
||
3404 | P: PByteArray; |
||
3405 | I,C: Integer; |
||
3406 | begin |
||
3407 | C := 1; |
||
3408 | P := @Init_State; |
||
3409 | Move(Key, P^, Size); |
||
3410 | for I := Size to 47 do P[I] := P[I - Size] + P[I - Size +1]; |
||
3411 | for I := 0 to 31 do |
||
3412 | if P[I] = 0 then |
||
3413 | begin |
||
3414 | P[I] := C; |
||
3415 | Inc(C); |
||
3416 | end; |
||
3417 | end; |
||
3418 | |||
3419 | procedure GP8(Data: PLongArray); |
||
3420 | var |
||
3421 | I,I2: Integer; |
||
3422 | NewX: array[0..3] of LongWord; |
||
3423 | X1,X2,X3,X4: LongWord; |
||
3424 | Y1,Y2: LongWord; |
||
3425 | begin |
||
3426 | I := 0; |
||
3427 | I2 := 0; |
||
3428 | while I < 8 do |
||
3429 | begin |
||
3430 | X1 := Init_State.X[I2] shr 16; |
||
3431 | X2 := X1 * X1; |
||
3432 | X3 := X2 * X1; |
||
3433 | X4 := X3 * X1; |
||
3434 | Y1 := Init_State.Coef[I][0] * X4 + |
||
3435 | Init_State.Coef[I][1] * X3 + |
||
3436 | Init_State.Coef[I][2] * X2 + |
||
3437 | Init_State.Coef[I][3] * X1 + 1; |
||
3438 | X1 := Init_State.X[I2] and $FFFF; |
||
3439 | X2 := X1 * X1; |
||
3440 | X3 := X2 * X1; |
||
3441 | X4 := X3 * X1; |
||
3442 | Y2 := Init_State.Coef[I +1][0] * X4 + |
||
3443 | Init_State.Coef[I +2][1] * X3 + |
||
3444 | Init_State.Coef[I +3][2] * X2 + |
||
3445 | Init_State.Coef[I +4][3] * X1 + 1; |
||
3446 | Data[I2] := Y1 shl 16 or Y2 and $FFFF; |
||
3447 | NewX[I2] := Y1 and $FFFF0000 or Y2 shr 16; |
||
3448 | Inc(I2); |
||
3449 | Inc(I, 2); |
||
3450 | end; |
||
3451 | Init_State.X[0] := NewX[0] shr 16 or NewX[3] shl 16; |
||
3452 | Init_State.X[1] := NewX[0] shl 16 or NewX[1] shr 16; |
||
3453 | Init_State.X[2] := NewX[1] shl 16 or NewX[2] shr 16; |
||
3454 | Init_State.X[3] := NewX[2] shl 16 or NewX[3] shr 16; |
||
3455 | end; |
||
3456 | |||
3457 | var |
||
3458 | I,J: Integer; |
||
3459 | T: array[0..3] of Integer; |
||
3460 | P: PLongArray; |
||
3461 | begin |
||
3462 | FillChar(Init_State, SizeOf(Init_State), 0); |
||
3463 | FillChar(T, SizeOf(T), 0); |
||
3464 | P := Pointer(PChar(FUser) + 12); |
||
3465 | ExpandKey; |
||
3466 | for I := 0 to 7 do GP8(@T); |
||
3467 | for I := 0 to 11 do |
||
3468 | begin |
||
3469 | for J := 0 to 7 do GP8(@P[I * 32 + J * 4]); |
||
3470 | GP8(@T); |
||
3471 | end; |
||
3472 | GP8(@T); |
||
3473 | I := T[3] and $7F; |
||
3474 | P[I + 3] := P[I + 3] or 1; |
||
3475 | P := FUser; |
||
3476 | P[0] := T[3] shr 24 and $FF; |
||
3477 | P[1] := T[3] shr 16 and $FF; |
||
3478 | P[2] := T[3] shr 8 and $FF; |
||
3479 | ProtectBuffer(Init_State, SizeOf(Init_State)); |
||
3480 | end; |
||
3481 | |||
3482 | procedure TCipher_SCOP.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3483 | var |
||
3484 | I,J: Byte; |
||
3485 | T2,T3,T1: LongWord; |
||
3486 | P: PLongArray; |
||
3487 | W: Integer; |
||
3488 | begin |
||
3489 | P := FUser; |
||
3490 | I := P[0]; |
||
3491 | J := P[1]; |
||
3492 | T3 := P[2]; |
||
3493 | for W := 0 to Size div 4 -1 do |
||
3494 | begin |
||
3495 | T1 := P[J + 3 + 128]; Inc(J, T3); |
||
3496 | T2 := P[J + 3 + 128]; |
||
3497 | PLongArray(Dest)[W] := PLongArray(Source)[W] + T1 + T2; |
||
3498 | T3 := T2 + P[I + 3]; Inc(I); |
||
3499 | P[J + 3 + 128] := T3; |
||
3500 | Inc(J, T2); |
||
3501 | end; |
||
3502 | P[0] := I; |
||
3503 | P[1] := J; |
||
3504 | P[2] := T3; |
||
3505 | end; |
||
3506 | |||
3507 | procedure TCipher_SCOP.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3508 | var |
||
3509 | I, J: Byte; |
||
3510 | T1,T2,T3: LongWord; |
||
3511 | P: PLongArray; |
||
3512 | W: Integer; |
||
3513 | begin |
||
3514 | P := FUser; |
||
3515 | I := P[0]; |
||
3516 | J := P[1]; |
||
3517 | T3 := P[2]; |
||
3518 | for W := 0 to Size div 4 -1 do |
||
3519 | begin |
||
3520 | T1 := P[J + 3 + 128]; Inc(J, T3); |
||
3521 | T2 := P[J + 3 + 128]; |
||
3522 | PLongArray(Dest)[W] := PLongArray(Source)[W] - T1 - T2; |
||
3523 | T3 := T2 + P[I + 3]; |
||
3524 | Inc(I); |
||
3525 | P[J + 3 + 128] := T3; |
||
3526 | Inc(J, T2); |
||
3527 | end; |
||
3528 | P[0] := I; |
||
3529 | P[1] := J; |
||
3530 | P[2] := T3; |
||
3531 | end; |
||
3532 | |||
3533 | |||
3534 | // .TCipher_Sapphire |
||
3535 | type |
||
3536 | PSapphireKey = ^TSapphireKey; |
||
3537 | TSapphireKey = packed record |
||
3538 | Cards: array[0..255] of LongWord; |
||
3539 | Rotor: LongWord; |
||
3540 | Ratchet: LongWord; |
||
3541 | Avalanche: LongWord; |
||
3542 | Plain: LongWord; |
||
3543 | Cipher: LongWord; |
||
3544 | end; |
||
3545 | |||
3546 | class function TCipher_Sapphire.Context: TCipherContext; |
||
3547 | begin |
||
3548 | Result.KeySize := 1024; |
||
3549 | Result.BlockSize := 1; |
||
3550 | Result.BufferSize := 32; |
||
3551 | Result.UserSize := SizeOf(TSapphireKey); |
||
3552 | Result.UserSave := True; |
||
3553 | end; |
||
3554 | |||
3555 | procedure TCipher_Sapphire.DoInit(const Key; Size: Integer); |
||
3556 | var |
||
3557 | Sum: Byte; |
||
3558 | P: Integer; |
||
3559 | |||
3560 | function KeyRand(Max: LongWord): Byte; |
||
3561 | var |
||
3562 | I,M: LongWord; |
||
3563 | begin |
||
3564 | Result := 0; |
||
3565 | if Max = 0 then Exit; |
||
3566 | I := 0; |
||
3567 | M := 1; |
||
3568 | while M < Max do |
||
3569 | Inc(M, M or 1); |
||
3570 | repeat |
||
3571 | Inc(Sum, TByteArray(Key)[P]); |
||
3572 | Inc(P); |
||
3573 | if P >= Size then |
||
3574 | begin |
||
3575 | P := 0; |
||
3576 | Inc(Sum, Size); |
||
3577 | end; |
||
3578 | Result := M and Sum; |
||
3579 | Inc(I); |
||
3580 | if I > 11 then Result := Result mod Max; |
||
3581 | until Result <= Max; |
||
3582 | end; |
||
3583 | |||
3584 | var |
||
3585 | I,S,T: Integer; |
||
3586 | begin |
||
3587 | with PSapphireKey(FUser)^ do |
||
3588 | if Size <= 0 then |
||
3589 | begin |
||
3590 | Rotor := 1; |
||
3591 | Ratchet := 3; |
||
3592 | Avalanche := 5; |
||
3593 | Plain := 7; |
||
3594 | Cipher := 11; |
||
3595 | for I := 0 to 255 do Cards[I] := 255 - I; |
||
3596 | end else |
||
3597 | begin |
||
3598 | for I := 0 to 255 do Cards[I] := I; |
||
3599 | P := 0; |
||
3600 | Sum := 0; |
||
3601 | for I := 255 downto 1 do |
||
3602 | begin |
||
3603 | S := KeyRand(I); |
||
3604 | T := Cards[I]; |
||
3605 | Cards[I] := Cards[S]; |
||
3606 | Cards[S] := T; |
||
3607 | end; |
||
3608 | Rotor := Cards[1]; |
||
3609 | Ratchet := Cards[3]; |
||
3610 | Avalanche := Cards[5]; |
||
3611 | Plain := Cards[7]; |
||
3612 | Cipher := Cards[Sum]; |
||
3613 | end; |
||
3614 | end; |
||
3615 | |||
3616 | procedure TCipher_Sapphire.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3617 | var |
||
3618 | T: LongWord; |
||
3619 | I: Integer; |
||
3620 | begin |
||
3621 | with PSapphireKey(FUser)^ do |
||
3622 | for I := 0 to Size -1 do |
||
3623 | begin |
||
3624 | Ratchet := (Ratchet + Cards[Rotor]) and $FF; |
||
3625 | Rotor := (Rotor + 1) and $FF; |
||
3626 | T := Cards[Cipher]; |
||
3627 | Cards[Cipher] := Cards[Ratchet]; |
||
3628 | Cards[Ratchet] := Cards[Plain]; |
||
3629 | Cards[Plain] := Cards[Rotor]; |
||
3630 | Cards[Rotor] := T; |
||
3631 | Avalanche := (Avalanche + Cards[T]) and $FF; |
||
3632 | T := (Cards[Plain] + Cards[Cipher] + Cards[Avalanche]) and $FF; |
||
3633 | Plain := PByteArray(Source)[I]; |
||
3634 | Cipher := Plain xor Cards[Cards[T]] xor Cards[(Cards[Ratchet] + Cards[Rotor]) and $FF]; |
||
3635 | PByteArray(Dest)[I] := Cipher; |
||
3636 | end; |
||
3637 | end; |
||
3638 | |||
3639 | procedure TCipher_Sapphire.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3640 | var |
||
3641 | T: LongWord; |
||
3642 | I: Integer; |
||
3643 | begin |
||
3644 | with PSapphireKey(FUser)^ do |
||
3645 | for I := 0 to Size -1 do |
||
3646 | begin |
||
3647 | Ratchet := (Ratchet + Cards[Rotor]) and $FF; |
||
3648 | Rotor := (Rotor + 1) and $FF; |
||
3649 | T := Cards[Cipher]; |
||
3650 | Cards[Cipher] := Cards[Ratchet]; |
||
3651 | Cards[Ratchet] := Cards[Plain]; |
||
3652 | Cards[Plain] := Cards[Rotor]; |
||
3653 | Cards[Rotor] := T; |
||
3654 | Avalanche := (Avalanche + Cards[T]) and $FF; |
||
3655 | T := (Cards[Plain] + Cards[Cipher] + Cards[Avalanche]) and $FF; |
||
3656 | Cipher := PByteArray(Source)[I]; |
||
3657 | Plain := Cipher xor Cards[Cards[T]] xor Cards[(Cards[Ratchet] + Cards[Rotor]) and $FF]; |
||
3658 | PByteArray(Dest)[I] := Plain; |
||
3659 | end; |
||
3660 | end; |
||
3661 | |||
3662 | // .DES |
||
3663 | procedure DES_Func(Source, Dest, Key: PLongArray); |
||
3664 | var |
||
3665 | L,R,X,Y,I: LongWord; |
||
3666 | begin |
||
3667 | L := SwapLong(Source[0]); |
||
3668 | R := SwapLong(Source[1]); |
||
3669 | |||
3670 | X := (L shr 4 xor R) and $0F0F0F0F; R := R xor X; L := L xor X shl 4; |
||
3671 | X := (L shr 16 xor R) and $0000FFFF; R := R xor X; L := L xor X shl 16; |
||
3672 | X := (R shr 2 xor L) and $33333333; L := L xor X; R := R xor X shl 2; |
||
3673 | X := (R shr 8 xor L) and $00FF00FF; L := L xor X; R := R xor X shl 8; |
||
3674 | |||
3675 | R := R shl 1 or R shr 31; |
||
3676 | X := (L xor R) and $AAAAAAAA; |
||
3677 | R := R xor X; |
||
3678 | L := L xor X; |
||
3679 | L := L shl 1 or L shr 31; |
||
3680 | |||
3681 | for I := 0 to 7 do |
||
3682 | begin |
||
3683 | X := (R shl 28 or R shr 4) xor Key[0]; |
||
3684 | Y := R xor Key[1]; |
||
3685 | L := L xor (DES_Data[0, X and $3F] or DES_Data[1, X shr 8 and $3F] or |
||
3686 | DES_Data[2, X shr 16 and $3F] or DES_Data[3, X shr 24 and $3F] or |
||
3687 | DES_Data[4, Y and $3F] or DES_Data[5, Y shr 8 and $3F] or |
||
3688 | DES_Data[6, Y shr 16 and $3F] or DES_Data[7, Y shr 24 and $3F]); |
||
3689 | |||
3690 | X := (L shl 28 or L shr 4) xor Key[2]; |
||
3691 | Y := L xor Key[3]; |
||
3692 | R := R xor (DES_Data[0, X and $3F] or DES_Data[1, X shr 8 and $3F] or |
||
3693 | DES_Data[2, X shr 16 and $3F] or DES_Data[3, X shr 24 and $3F] or |
||
3694 | DES_Data[4, Y and $3F] or DES_Data[5, Y shr 8 and $3F] or |
||
3695 | DES_Data[6, Y shr 16 and $3F] or DES_Data[7, Y shr 24 and $3F]); |
||
3696 | Key := @Key[4]; |
||
3697 | end; |
||
3698 | |||
3699 | R := R shl 31 or R shr 1; |
||
3700 | X := (L xor R) and $AAAAAAAA; |
||
3701 | R := R xor X; |
||
3702 | L := L xor X; |
||
3703 | L := L shl 31 or L shr 1; |
||
3704 | |||
3705 | X := (L shr 8 xor R) and $00FF00FF; R := R xor X; L := L xor X shl 8; |
||
3706 | X := (L shr 2 xor R) and $33333333; R := R xor X; L := L xor X shl 2; |
||
3707 | X := (R shr 16 xor L) and $0000FFFF; L := L xor X; R := R xor X shl 16; |
||
3708 | X := (R shr 4 xor L) and $0F0F0F0F; L := L xor X; R := R xor X shl 4; |
||
3709 | |||
3710 | Dest[0] := SwapLong(R); |
||
3711 | Dest[1] := SwapLong(L); |
||
3712 | end; |
||
3713 | |||
3714 | // .TCipher_1DES |
||
3715 | class function TCipher_1DES.Context: TCipherContext; |
||
3716 | begin |
||
3717 | Result.KeySize := 8; |
||
3718 | Result.BlockSize := 8; |
||
3719 | Result.BufferSize := 8; |
||
3720 | Result.UserSize := 32 * 4 * 2; |
||
3721 | Result.UserSave := False; |
||
3722 | end; |
||
3723 | |||
3724 | procedure TCipher_1DES.DoInitKey(const Data: array of Byte; Key: PLongArray; Reverse: Boolean); |
||
3725 | const |
||
3726 | ROT: array[0..15] of Byte = (1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28); |
||
3727 | var |
||
3728 | I,J,L,M,N: LongWord; |
||
3729 | PC_M,PC_R: array[0..55] of Byte; |
||
3730 | K: array[0..31] of LongWord; |
||
3731 | begin |
||
3732 | FillChar(K, SizeOf(K), 0); |
||
3733 | for I := 0 to 55 do |
||
3734 | if Data[DES_PC1[I] shr 3] and ($80 shr (DES_PC1[I] and $07)) <> 0 then PC_M[I] := 1 |
||
3735 | else PC_M[I] := 0; |
||
3736 | for I := 0 to 15 do |
||
3737 | begin |
||
3738 | if Reverse then M := (15 - I) shl 1 |
||
3739 | else M := I shl 1; |
||
3740 | N := M + 1; |
||
3741 | for J := 0 to 27 do |
||
3742 | begin |
||
3743 | L := J + ROT[I]; |
||
3744 | if L < 28 then PC_R[J] := PC_M[L] else PC_R[J] := PC_M[L - 28]; |
||
3745 | end; |
||
3746 | for J := 28 to 55 do |
||
3747 | begin |
||
3748 | L := J + ROT[I]; |
||
3749 | if L < 56 then PC_R[J] := PC_M[L] else PC_R[J] := PC_M[L - 28]; |
||
3750 | end; |
||
3751 | L := $1000000; |
||
3752 | for J := 0 to 23 do |
||
3753 | begin |
||
3754 | L := L shr 1; |
||
3755 | if PC_R[DES_PC2[J ]] <> 0 then K[M] := K[M] or L; |
||
3756 | if PC_R[DES_PC2[J + 24]] <> 0 then K[N] := K[N] or L; |
||
3757 | end; |
||
3758 | end; |
||
3759 | for I := 0 to 15 do |
||
3760 | begin |
||
3761 | M := I shl 1; |
||
3762 | N := M + 1; |
||
3763 | Key[0] := K[M] and $00FC0000 shl 6 or |
||
3764 | K[M] and $00000FC0 shl 10 or |
||
3765 | K[N] and $00FC0000 shr 10 or |
||
3766 | K[N] and $00000FC0 shr 6; |
||
3767 | Key[1] := K[M] and $0003F000 shl 12 or |
||
3768 | K[M] and $0000003F shl 16 or |
||
3769 | K[N] and $0003F000 shr 4 or |
||
3770 | K[N] and $0000003F; |
||
3771 | Key := @Key[2]; |
||
3772 | end; |
||
3773 | ProtectBuffer(K, SizeOf(K)); |
||
3774 | ProtectBuffer(PC_M, SizeOf(PC_M)); |
||
3775 | ProtectBuffer(PC_R, SizeOf(PC_R)); |
||
3776 | end; |
||
3777 | |||
3778 | procedure TCipher_1DES.DoInit(const Key; Size: Integer); |
||
3779 | var |
||
3780 | K: array[0..7] of Byte; |
||
3781 | begin |
||
3782 | FillChar(K, SizeOf(K), 0); |
||
3783 | Move(Key, K, Size); |
||
3784 | DoInitKey(K, FUser, False); |
||
3785 | DoInitKey(K, @PLongArray(FUser)[32], True); |
||
3786 | ProtectBuffer(K, SizeOf(K)); |
||
3787 | end; |
||
3788 | |||
3789 | procedure TCipher_1DES.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3790 | begin |
||
3791 | Assert(Size = Context.BufferSize); |
||
3792 | DES_Func(Source, Dest, FUser); |
||
3793 | end; |
||
3794 | |||
3795 | procedure TCipher_1DES.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3796 | begin |
||
3797 | Assert(Size = Context.BufferSize); |
||
3798 | DES_Func(Source,Dest, @PLongArray(FUser)[32]); |
||
3799 | end; |
||
3800 | |||
3801 | // .TCipher_2DES |
||
3802 | class function TCipher_2DES.Context: TCipherContext; |
||
3803 | begin |
||
3804 | Result.KeySize := 16; |
||
3805 | Result.BlockSize := 8; |
||
3806 | Result.BufferSize := 8; |
||
3807 | Result.UserSize := 32 * 4 * 2 * 2; |
||
3808 | Result.UserSave := False; |
||
3809 | end; |
||
3810 | |||
3811 | procedure TCipher_2DES.DoInit(const Key; Size: Integer); |
||
3812 | var |
||
3813 | K: array[0..15] of Byte; |
||
3814 | P: PLongArray; |
||
3815 | begin |
||
3816 | FillChar(K, SizeOf(K), 0); |
||
3817 | Move(Key, K, Size); |
||
3818 | P := FUser; |
||
3819 | DoInitKey(K[0], @P[ 0], False); |
||
3820 | DoInitKey(K[8], @P[32], True); |
||
3821 | DoInitKey(K[0], @P[64], True); |
||
3822 | DoInitKey(K[8], @P[96], False); |
||
3823 | ProtectBuffer(K, SizeOf(K)); |
||
3824 | end; |
||
3825 | |||
3826 | procedure TCipher_2DES.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3827 | begin |
||
3828 | Assert(Size = Context.BufferSize); |
||
3829 | DES_Func(Source, Dest, FUser); |
||
3830 | DES_Func(Source, Dest, @PLongArray(FUser)[32]); |
||
3831 | DES_Func(Source, Dest, FUser); |
||
3832 | end; |
||
3833 | |||
3834 | procedure TCipher_2DES.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3835 | begin |
||
3836 | Assert(Size = Context.BufferSize); |
||
3837 | DES_Func(Source, Dest, @PLongArray(FUser)[64]); |
||
3838 | DES_Func(Source, Dest, @PLongArray(FUser)[96]); |
||
3839 | DES_Func(Source, Dest, @PLongArray(FUser)[64]); |
||
3840 | end; |
||
3841 | |||
3842 | // .TCipher_3DES |
||
3843 | class function TCipher_3DES.Context: TCipherContext; |
||
3844 | begin |
||
3845 | Result.KeySize := 24; |
||
3846 | Result.BlockSize := 8; |
||
3847 | Result.BufferSize := 8; |
||
3848 | Result.UserSize := 32 * 4 * 2 * 3; |
||
3849 | Result.UserSave := False; |
||
3850 | end; |
||
3851 | |||
3852 | procedure TCipher_3DES.DoInit(const Key; Size: Integer); |
||
3853 | var |
||
3854 | K: array[0..23] of Byte; |
||
3855 | P: PLongArray; |
||
3856 | begin |
||
3857 | FillChar(K, SizeOf(K), 0); |
||
3858 | Move(Key, K, Size); |
||
3859 | P := FUser; |
||
3860 | DoInitKey(K[ 0], @P[ 0], False); |
||
3861 | DoInitKey(K[ 8], @P[ 32], True); |
||
3862 | DoInitKey(K[16], @P[ 64], False); |
||
3863 | DoInitKey(K[16], @P[ 96], True); |
||
3864 | DoInitKey(K[ 8], @P[128], False); |
||
3865 | DoInitKey(K[ 0], @P[160], True); |
||
3866 | ProtectBuffer(K, SizeOf(K)); |
||
3867 | end; |
||
3868 | |||
3869 | procedure TCipher_3DES.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3870 | begin |
||
3871 | Assert(Size = Context.BufferSize); |
||
3872 | DES_Func(Source, Dest, @PLongArray(FUser)[ 0]); |
||
3873 | DES_Func(Source, Dest, @PLongArray(FUser)[32]); |
||
3874 | DES_Func(Source, Dest, @PLongArray(FUser)[64]); |
||
3875 | end; |
||
3876 | |||
3877 | procedure TCipher_3DES.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3878 | begin |
||
3879 | Assert(Size = Context.BufferSize); |
||
3880 | DES_Func(Source, Dest, @PLongArray(FUser)[96]); |
||
3881 | DES_Func(Source, Dest, @PLongArray(FUser)[128]); |
||
3882 | DES_Func(Source, Dest, @PLongArray(FUser)[160]); |
||
3883 | end; |
||
3884 | |||
3885 | // .TCipher_2DDES |
||
3886 | class function TCipher_2DDES.Context: TCipherContext; |
||
3887 | begin |
||
3888 | Result := inherited Context; |
||
3889 | Result.BlockSize := 16; |
||
3890 | Result.BufferSize := 16; |
||
3891 | end; |
||
3892 | |||
3893 | procedure TCipher_2DDES.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3894 | var |
||
3895 | T: LongWord; |
||
3896 | S: PLongArray absolute Source; |
||
3897 | D: PLongArray absolute Dest; |
||
3898 | begin |
||
3899 | Assert(Size = Context.BufferSize); |
||
3900 | |||
3901 | DES_Func(@S[0], @D[0], FUser); |
||
3902 | DES_Func(@S[2], @D[2], FUser); |
||
3903 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3904 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]); |
||
3905 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]); |
||
3906 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3907 | DES_Func(@D[0], @D[0], FUser); |
||
3908 | DES_Func(@D[2], @D[2], FUser); |
||
3909 | end; |
||
3910 | |||
3911 | procedure TCipher_2DDES.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3912 | var |
||
3913 | T: LongWord; |
||
3914 | S: PLongArray absolute Source; |
||
3915 | D: PLongArray absolute Dest; |
||
3916 | begin |
||
3917 | Assert(Size = Context.BufferSize); |
||
3918 | |||
3919 | DES_Func(@S[0], @D[0], @PLongArray(FUser)[64]); |
||
3920 | DES_Func(@S[2], @D[2], @PLongArray(FUser)[64]); |
||
3921 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3922 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[96]); |
||
3923 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[96]); |
||
3924 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3925 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]); |
||
3926 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]); |
||
3927 | end; |
||
3928 | |||
3929 | // .TCipher_3DDES |
||
3930 | class function TCipher_3DDES.Context: TCipherContext; |
||
3931 | begin |
||
3932 | Result := inherited Context; |
||
3933 | Result.BlockSize := 16; |
||
3934 | Result.BufferSize := 16; |
||
3935 | end; |
||
3936 | |||
3937 | procedure TCipher_3DDES.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3938 | var |
||
3939 | T: LongWord; |
||
3940 | S: PLongArray absolute Source; |
||
3941 | D: PLongArray absolute Dest; |
||
3942 | begin |
||
3943 | Assert(Size = Context.BufferSize); |
||
3944 | |||
3945 | DES_Func(@S[0], @D[0], FUser); |
||
3946 | DES_Func(@S[2], @D[2], FUser); |
||
3947 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3948 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]); |
||
3949 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]); |
||
3950 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3951 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]); |
||
3952 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]); |
||
3953 | end; |
||
3954 | |||
3955 | procedure TCipher_3DDES.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
3956 | var |
||
3957 | T: LongWord; |
||
3958 | S: PLongArray absolute Source; |
||
3959 | D: PLongArray absolute Dest; |
||
3960 | begin |
||
3961 | Assert(Size = Context.BufferSize); |
||
3962 | |||
3963 | DES_Func(@S[0], @D[0], @PLongArray(FUser)[96]); |
||
3964 | DES_Func(@S[2], @D[2], @PLongArray(FUser)[96]); |
||
3965 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3966 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[128]); |
||
3967 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[128]); |
||
3968 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3969 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[160]); |
||
3970 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[160]); |
||
3971 | end; |
||
3972 | |||
3973 | |||
3974 | // .TCipher_3TDES |
||
3975 | class function TCipher_3TDES.Context: TCipherContext; |
||
3976 | begin |
||
3977 | Result := inherited Context; |
||
3978 | Result.BlockSize := 24; |
||
3979 | Result.BufferSize := 24; |
||
3980 | end; |
||
3981 | |||
3982 | procedure TCipher_3TDES.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
3983 | var |
||
3984 | T: LongWord; |
||
3985 | S: PLongArray absolute Source; |
||
3986 | D: PLongArray absolute Dest; |
||
3987 | begin |
||
3988 | Assert(Size = Context.BufferSize); |
||
3989 | |||
3990 | DES_Func(@S[0], @D[0], FUser); |
||
3991 | DES_Func(@S[2], @D[2], FUser); |
||
3992 | DES_Func(@S[4], @D[4], FUser); |
||
3993 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3994 | T := D[3]; D[3] := D[4]; D[4] := T; |
||
3995 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]); |
||
3996 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]); |
||
3997 | DES_Func(@D[4], @D[4], @PLongArray(FUser)[32]); |
||
3998 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
3999 | T := D[3]; D[3] := D[4]; D[4] := T; |
||
4000 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]); |
||
4001 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]); |
||
4002 | DES_Func(@D[4], @D[4], @PLongArray(FUser)[64]); |
||
4003 | end; |
||
4004 | |||
4005 | procedure TCipher_3TDES.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
4006 | var |
||
4007 | T: LongWord; |
||
4008 | S: PLongArray absolute Source; |
||
4009 | D: PLongArray absolute Dest; |
||
4010 | begin |
||
4011 | Assert(Size = Context.BufferSize); |
||
4012 | |||
4013 | DES_Func(@S[0], @D[0], @PLongArray(FUser)[96]); |
||
4014 | DES_Func(@S[2], @D[2], @PLongArray(FUser)[96]); |
||
4015 | DES_Func(@S[4], @D[4], @PLongArray(FUser)[96]); |
||
4016 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
4017 | T := D[3]; D[3] := D[4]; D[4] := T; |
||
4018 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[128]); |
||
4019 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[128]); |
||
4020 | DES_Func(@D[4], @D[4], @PLongArray(FUser)[128]); |
||
4021 | T := D[1]; D[1] := D[2]; D[2] := T; |
||
4022 | T := D[3]; D[3] := D[4]; D[4] := T; |
||
4023 | DES_Func(@D[0], @D[0], @PLongArray(FUser)[160]); |
||
4024 | DES_Func(@D[2], @D[2], @PLongArray(FUser)[160]); |
||
4025 | DES_Func(@D[4], @D[4], @PLongArray(FUser)[160]); |
||
4026 | end; |
||
4027 | |||
4028 | |||
4029 | // .TCipher_3Way |
||
4030 | type |
||
4031 | P3Way_Key = ^T3Way_Key; |
||
4032 | T3Way_Key = packed record |
||
4033 | E_Key: array[0..2] of LongWord; |
||
4034 | E_Data: array[0..11] of LongWord; |
||
4035 | D_Key: array[0..2] of LongWord; |
||
4036 | D_Data: array[0..11] of LongWord; |
||
4037 | end; |
||
4038 | |||
4039 | class function TCipher_3Way.Context: TCipherContext; |
||
4040 | begin |
||
4041 | Result.KeySize := 12; |
||
4042 | Result.BlockSize := 12; |
||
4043 | Result.BufferSize := 12; |
||
4044 | Result.UserSize := SizeOf(T3Way_Key); |
||
4045 | Result.UserSave := False; |
||
4046 | end; |
||
4047 | |||
4048 | procedure TCipher_3Way.DoInit(const Key; Size: Integer); |
||
4049 | |||
4050 | procedure RANDGenerate(Start: LongWord; var P: Array of LongWord); |
||
4051 | var |
||
4052 | I: Integer; |
||
4053 | begin |
||
4054 | for I := 0 to 11 do |
||
4055 | begin |
||
4056 | P[I] := Start; |
||
4057 | Start := Start shl 1; |
||
4058 | if Start and $10000 <> 0 then Start := Start xor $11011; |
||
4059 | end; |
||
4060 | end; |
||
4061 | |||
4062 | var |
||
4063 | A0,A1,A2: LongWord; |
||
4064 | B0,B1,B2: LongWord; |
||
4065 | begin |
||
4066 | with P3Way_Key(FUser)^ do |
||
4067 | begin |
||
4068 | Move(Key, E_Key, Size); |
||
4069 | Move(Key, D_Key, Size); |
||
4070 | RANDGenerate($0B0B, E_Data); |
||
4071 | RANDGenerate($B1B1, D_Data); |
||
4072 | A0 := D_Key[0]; |
||
4073 | A1 := D_Key[1]; |
||
4074 | A2 := D_Key[2]; |
||
4075 | B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor |
||
4076 | A1 shr 24 xor A2 shl 8 xor A2 shr 8 xor A0 shl 24 xor |
||
4077 | A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl 8; |
||
4078 | B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor |
||
4079 | A2 shr 24 xor A0 shl 8 xor A0 shr 8 xor A1 shl 24 xor |
||
4080 | A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl 8; |
||
4081 | B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor |
||
4082 | A0 shr 24 xor A1 shl 8 xor A1 shr 8 xor A2 shl 24 xor |
||
4083 | A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl 8; |
||
4084 | D_Key[2] := SwapBits(B0, 0); |
||
4085 | D_Key[1] := SwapBits(B1, 0); |
||
4086 | D_Key[0] := SwapBits(B2, 0); |
||
4087 | end; |
||
4088 | end; |
||
4089 | |||
4090 | procedure TCipher_3Way.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
4091 | var |
||
4092 | I: Integer; |
||
4093 | A0,A1,A2: LongWord; |
||
4094 | B0,B1,B2: LongWord; |
||
4095 | K0,K1,K2: LongWord; |
||
4096 | E: PLongWord; |
||
4097 | begin |
||
4098 | Assert(Size = Context.BufferSize); |
||
4099 | |||
4100 | with P3Way_Key(FUser)^ do |
||
4101 | begin |
||
4102 | K0 := E_Key[0]; |
||
4103 | K1 := E_Key[1]; |
||
4104 | K2 := E_Key[2]; |
||
4105 | E := @E_Data; |
||
4106 | end; |
||
4107 | A0 := PLongArray(Source)[0]; |
||
4108 | A1 := PLongArray(Source)[1]; |
||
4109 | A2 := PLongArray(Source)[2]; |
||
4110 | for I := 0 to 10 do |
||
4111 | begin |
||
4112 | A0 := A0 xor K0 xor E^ shl 16; |
||
4113 | A1 := A1 xor K1; |
||
4114 | A2 := A2 xor K2 xor E^; |
||
4115 | Inc(E); |
||
4116 | |||
4117 | B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor |
||
4118 | A1 shr 24 xor A2 shl 8 xor A2 shr 8 xor A0 shl 24 xor |
||
4119 | A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl 8; |
||
4120 | B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor |
||
4121 | A2 shr 24 xor A0 shl 8 xor A0 shr 8 xor A1 shl 24 xor |
||
4122 | A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl 8; |
||
4123 | B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor |
||
4124 | A0 shr 24 xor A1 shl 8 xor A1 shr 8 xor A2 shl 24 xor |
||
4125 | A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl 8; |
||
4126 | B0 := B0 shr 10 or B0 shl 22; |
||
4127 | B2 := B2 shl 1 or B2 shr 31; |
||
4128 | A0 := B0 xor (B1 or not B2); |
||
4129 | A1 := B1 xor (B2 or not B0); |
||
4130 | A2 := B2 xor (B0 or not B1); |
||
4131 | A0 := A0 shl 1 or A0 shr 31; |
||
4132 | A2 := A2 shr 10 or A2 shl 22; |
||
4133 | end; |
||
4134 | A0 := A0 xor K0 xor E^ shl 16; |
||
4135 | A1 := A1 xor K1; |
||
4136 | A2 := A2 xor K2 xor E^; |
||
4137 | PLongArray(Dest)[0] := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor |
||
4138 | A1 shr 24 xor A2 shl 8 xor A2 shr 8 xor A0 shl 24 xor |
||
4139 | A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl 8; |
||
4140 | PLongArray(Dest)[1] := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor |
||
4141 | A2 shr 24 xor A0 shl 8 xor A0 shr 8 xor A1 shl 24 xor |
||
4142 | A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl 8; |
||
4143 | PLongArray(Dest)[2] := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor |
||
4144 | A0 shr 24 xor A1 shl 8 xor A1 shr 8 xor A2 shl 24 xor |
||
4145 | A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl 8; |
||
4146 | end; |
||
4147 | |||
4148 | procedure TCipher_3Way.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
4149 | var |
||
4150 | I: Integer; |
||
4151 | A0,A1,A2: LongWord; |
||
4152 | B0,B1,B2: LongWord; |
||
4153 | K0,K1,K2: LongWord; |
||
4154 | E: PLongWord; |
||
4155 | begin |
||
4156 | Assert(Size = Context.BufferSize); |
||
4157 | |||
4158 | with P3Way_Key(FUser)^ do |
||
4159 | begin |
||
4160 | K0 := D_Key[0]; |
||
4161 | K1 := D_Key[1]; |
||
4162 | K2 := D_Key[2]; |
||
4163 | E := @D_Data; |
||
4164 | end; |
||
4165 | A0 := SwapBits(PLongArray(Source)[2], 0); |
||
4166 | A1 := SwapBits(PLongArray(Source)[1], 0); |
||
4167 | A2 := SwapBits(PLongArray(Source)[0], 0); |
||
4168 | for I := 0 to 10 do |
||
4169 | begin |
||
4170 | A0 := A0 xor K0 xor E^ shl 16; |
||
4171 | A1 := A1 xor K1; |
||
4172 | A2 := A2 xor K2 xor E^; |
||
4173 | Inc(E); |
||
4174 | |||
4175 | B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor |
||
4176 | A1 shr 24 xor A2 shl 8 xor A2 shr 8 xor A0 shl 24 xor |
||
4177 | A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl 8; |
||
4178 | B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor |
||
4179 | A2 shr 24 xor A0 shl 8 xor A0 shr 8 xor A1 shl 24 xor |
||
4180 | A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl 8; |
||
4181 | B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor |
||
4182 | A0 shr 24 xor A1 shl 8 xor A1 shr 8 xor A2 shl 24 xor |
||
4183 | A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl 8; |
||
4184 | B0 := B0 shr 10 or B0 shl 22; |
||
4185 | B2 := B2 shl 1 or B2 shr 31; |
||
4186 | A0 := B0 xor (B1 or not B2); |
||
4187 | A1 := B1 xor (B2 or not B0); |
||
4188 | A2 := B2 xor (B0 or not B1); |
||
4189 | A0 := A0 shl 1 or A0 shr 31; |
||
4190 | A2 := A2 shr 10 or A2 shl 22; |
||
4191 | end; |
||
4192 | A0 := A0 xor K0 xor E^ shl 16; |
||
4193 | A1 := A1 xor K1; |
||
4194 | A2 := A2 xor K2 xor E^; |
||
4195 | B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor |
||
4196 | A1 shr 24 xor A2 shl 8 xor A2 shr 8 xor A0 shl 24 xor |
||
4197 | A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl 8; |
||
4198 | B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor |
||
4199 | A2 shr 24 xor A0 shl 8 xor A0 shr 8 xor A1 shl 24 xor |
||
4200 | A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl 8; |
||
4201 | B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor |
||
4202 | A0 shr 24 xor A1 shl 8 xor A1 shr 8 xor A2 shl 24 xor |
||
4203 | A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl 8; |
||
4204 | |||
4205 | PLongArray(Dest)[2] := SwapBits(B0, 0); |
||
4206 | PLongArray(Dest)[1] := SwapBits(B1, 0); |
||
4207 | PLongArray(Dest)[0] := SwapBits(B2, 0); |
||
4208 | end; |
||
4209 | |||
4210 | |||
4211 | // .TCipher_Cast128 |
||
4212 | class function TCipher_Cast128.Context: TCipherContext; |
||
4213 | begin |
||
4214 | Result.KeySize := 16; |
||
4215 | Result.BlockSize := 8; |
||
4216 | Result.BufferSize := 8; |
||
4217 | Result.UserSize := 128; |
||
4218 | Result.UserSave := False; |
||
4219 | end; |
||
4220 | |||
4221 | procedure TCipher_Cast128.SetRounds(Value: Integer); |
||
4222 | begin |
||
4223 | if Value <> FRounds then |
||
4224 | begin |
||
4225 | if not (FState in [csNew, csInitialized, csDone]) then Done; |
||
4226 | if (FState <> csNew) and (Value <= 0) then Value := 16; |
||
4227 | FRounds := Value; |
||
4228 | end; |
||
4229 | end; |
||
4230 | |||
4231 | procedure TCipher_Cast128.DoInit(const Key; Size: Integer); |
||
4232 | var |
||
4233 | Z,X,T: array[0..3] of LongWord; |
||
4234 | K: PLongArray; |
||
4235 | I: LongWord; |
||
4236 | begin |
||
4237 | if FRounds <= 0 then |
||
4238 | if Size <= 10 then FRounds := 12 |
||
4239 | else FRounds := 16; |
||
4240 | K := FUser; |
||
4241 | FillChar(X, SizeOf(X), 0); |
||
4242 | Move(Key, X, Size); |
||
4243 | SwapLongBuffer(X, X, 4); |
||
4244 | I := 0; |
||
4245 | while I < 32 do |
||
4246 | begin |
||
4247 | if I and 4 = 0 then |
||
4248 | begin |
||
4249 | Z[0] := X[0] xor Cast128_Key[0, X[3] shr 16 and $FF] xor |
||
4250 | Cast128_Key[1, X[3] and $FF] xor |
||
4251 | Cast128_Key[2, X[3] shr 24] xor |
||
4252 | Cast128_Key[3, X[3] shr 8 and $FF] xor |
||
4253 | Cast128_Key[2, X[2] shr 24]; |
||
4254 | T[0] := Z[0]; |
||
4255 | Z[1] := X[2] xor Cast128_Key[0, Z[0] shr 24] xor |
||
4256 | Cast128_Key[1, Z[0] shr 8 and $FF] xor |
||
4257 | Cast128_Key[2, Z[0] shr 16 and $FF] xor |
||
4258 | Cast128_Key[3, Z[0] and $FF] xor |
||
4259 | Cast128_Key[3, X[2] shr 8 and $FF]; |
||
4260 | T[1] := Z[1]; |
||
4261 | Z[2] := X[3] xor Cast128_Key[0, Z[1] and $FF] xor |
||
4262 | Cast128_Key[1, Z[1] shr 8 and $FF] xor |
||
4263 | Cast128_Key[2, Z[1] shr 16 and $FF] xor |
||
4264 | Cast128_Key[3, Z[1] shr 24] xor |
||
4265 | Cast128_Key[0, X[2] shr 16 and $FF]; |
||
4266 | T[2] := Z[2]; |
||
4267 | Z[3] := X[1] xor Cast128_Key[0, Z[2] shr 8 and $FF] xor |
||
4268 | Cast128_Key[1, Z[2] shr 16 and $FF] xor |
||
4269 | Cast128_Key[2, Z[2] and $FF] xor |
||
4270 | Cast128_Key[3, Z[2] shr 24] xor |
||
4271 | Cast128_Key[1, X[2] and $FF]; |
||
4272 | T[3] := Z[3]; |
||
4273 | end else |
||
4274 | begin |
||
4275 | X[0] := Z[2] xor Cast128_Key[0, Z[1] shr 16 and $FF] xor |
||
4276 | Cast128_Key[1, Z[1] and $FF] xor |
||
4277 | Cast128_Key[2, Z[1] shr 24] xor |
||
4278 | Cast128_Key[3, Z[1] shr 8 and $FF] xor |
||
4279 | Cast128_Key[2, Z[0] shr 24]; |
||
4280 | T[0] := X[0]; |
||
4281 | X[1] := Z[0] xor Cast128_Key[0, X[0] shr 24] xor |
||
4282 | Cast128_Key[1, X[0] shr 8 and $FF] xor |
||
4283 | Cast128_Key[2, X[0] shr 16 and $FF] xor |
||
4284 | Cast128_Key[3, X[0] and $FF] xor |
||
4285 | Cast128_Key[3, Z[0] shr 8 and $FF]; |
||
4286 | T[1] := X[1]; |
||
4287 | X[2] := Z[1] xor Cast128_Key[0, X[1] and $FF] xor |
||
4288 | Cast128_Key[1, X[1] shr 8 and $FF] xor |
||
4289 | Cast128_Key[2, X[1] shr 16 and $FF] xor |
||
4290 | Cast128_Key[3, X[1] shr 24] xor |
||
4291 | Cast128_Key[0, Z[0] shr 16 and $FF]; |
||
4292 | T[2] := X[2]; |
||
4293 | X[3] := Z[3] xor Cast128_Key[0, X[2] shr 8 and $FF] xor |
||
4294 | Cast128_Key[1, X[2] shr 16 and $FF] xor |
||
4295 | Cast128_Key[2, X[2] and $FF] xor |
||
4296 | Cast128_Key[3, X[2] shr 24] xor |
||
4297 | Cast128_Key[1, Z[0] and $FF]; |
||
4298 | T[3] := X[3]; |
||
4299 | end; |
||
4300 | case I and 12 of |
||
4301 | 0,12: |
||
4302 | begin |
||
4303 | K[I +0] := Cast128_Key[0, T[2] shr 24] xor |
||
4304 | Cast128_Key[1, T[2] shr 16 and $FF] xor |
||
4305 | Cast128_Key[2, T[1] and $FF] xor |
||
4306 | Cast128_Key[3, T[1] shr 8 and $FF]; |
||
4307 | K[I +1] := Cast128_Key[0, T[2] shr 8 and $FF] xor |
||
4308 | Cast128_Key[1, T[2] and $FF] xor |
||
4309 | Cast128_Key[2, T[1] shr 16 and $FF] xor |
||
4310 | Cast128_Key[3, T[1] shr 24]; |
||
4311 | K[I +2] := Cast128_Key[0, T[3] shr 24] xor |
||
4312 | Cast128_Key[1, T[3] shr 16 and $FF] xor |
||
4313 | Cast128_Key[2, T[0] and $FF] xor |
||
4314 | Cast128_Key[3, T[0] shr 8 and $FF]; |
||
4315 | K[I +3] := Cast128_Key[0, T[3] shr 8 and $FF] xor |
||
4316 | Cast128_Key[1, T[3] and $FF] xor |
||
4317 | Cast128_Key[2, T[0] shr 16 and $FF] xor |
||
4318 | Cast128_Key[3, T[0] shr 24]; |
||
4319 | end; |
||
4320 | 4,8: |
||
4321 | begin |
||
4322 | K[I +0] := Cast128_Key[0, T[0] and $FF] xor |
||
4323 | Cast128_Key[1, T[0] shr 8 and $FF] xor |
||
4324 | Cast128_Key[2, T[3] shr 24] xor |
||
4325 | Cast128_Key[3, T[3] shr 16 and $FF]; |
||
4326 | K[I +1] := Cast128_Key[0, T[0] shr 16 and $FF] xor |
||
4327 | Cast128_Key[1, T[0] shr 24] xor |
||
4328 | Cast128_Key[2, T[3] shr 8 and $FF] xor |
||
4329 | Cast128_Key[3, T[3] and $FF]; |
||
4330 | K[I +2] := Cast128_Key[0, T[1] and $FF] xor |
||
4331 | Cast128_Key[1, T[1] shr 8 and $FF] xor |
||
4332 | Cast128_Key[2, T[2] shr 24] xor |
||
4333 | Cast128_Key[3, T[2] shr 16 and $FF]; |
||
4334 | K[I +3] := Cast128_Key[0, T[1] shr 16 and $FF] xor |
||
4335 | Cast128_Key[1, T[1] shr 24] xor |
||
4336 | Cast128_Key[2, T[2] shr 8 and $FF] xor |
||
4337 | Cast128_Key[3, T[2] and $FF]; |
||
4338 | end; |
||
4339 | end; |
||
4340 | case I and 12 of |
||
4341 | 0: begin |
||
4342 | K[I +0] := K[I +0] xor Cast128_Key[0, Z[0] shr 8 and $FF]; |
||
4343 | K[I +1] := K[I +1] xor Cast128_Key[1, Z[1] shr 8 and $FF]; |
||
4344 | K[I +2] := K[I +2] xor Cast128_Key[2, Z[2] shr 16 and $FF]; |
||
4345 | K[I +3] := K[I +3] xor Cast128_Key[3, Z[3] shr 24]; |
||
4346 | end; |
||
4347 | 4: begin |
||
4348 | K[I +0] := K[I +0] xor Cast128_Key[0, X[2] shr 24]; |
||
4349 | K[I +1] := K[I +1] xor Cast128_Key[1, X[3] shr 16 and $FF]; |
||
4350 | K[I +2] := K[I +2] xor Cast128_Key[2, X[0] and $FF]; |
||
4351 | K[I +3] := K[I +3] xor Cast128_Key[3, X[1] and $FF]; |
||
4352 | end; |
||
4353 | 8: begin |
||
4354 | K[I +0] := K[I +0] xor Cast128_Key[0, Z[2] shr 16 and $FF]; |
||
4355 | K[I +1] := K[I +1] xor Cast128_Key[1, Z[3] shr 24]; |
||
4356 | K[I +2] := K[I +2] xor Cast128_Key[2, Z[0] shr 8 and $FF]; |
||
4357 | K[I +3] := K[I +3] xor Cast128_Key[3, Z[1] shr 8 and $FF]; |
||
4358 | end; |
||
4359 | 12: begin |
||
4360 | K[I +0] := K[I +0] xor Cast128_Key[0, X[0] and $FF]; |
||
4361 | K[I +1] := K[I +1] xor Cast128_Key[1, X[1] and $FF]; |
||
4362 | K[I +2] := K[I +2] xor Cast128_Key[2, X[2] shr 24]; |
||
4363 | K[I +3] := K[I +3] xor Cast128_Key[3, X[3] shr 16 and $FF]; |
||
4364 | end; |
||
4365 | end; |
||
4366 | if I >= 16 then |
||
4367 | begin |
||
4368 | K[I +0] := K[I +0] and $1F; |
||
4369 | K[I +1] := K[I +1] and $1F; |
||
4370 | K[I +2] := K[I +2] and $1F; |
||
4371 | K[I +3] := K[I +3] and $1F; |
||
4372 | end; |
||
4373 | Inc(I, 4); |
||
4374 | end; |
||
4375 | ProtectBuffer(X, SizeOf(X)); |
||
4376 | ProtectBuffer(Z, SizeOf(Z)); |
||
4377 | ProtectBuffer(T, SizeOf(T)); |
||
4378 | end; |
||
4379 | |||
4380 | procedure TCipher_Cast128.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
4381 | var |
||
4382 | T,I,A,B: LongWord; |
||
4383 | K: PLongArray; |
||
4384 | begin |
||
4385 | Assert(Size = Context.BufferSize); |
||
4386 | |||
4387 | K := FUser; |
||
4388 | A := SwapLong(PLongArray(Source)[0]); |
||
4389 | B := SwapLong(PLongArray(Source)[1]); |
||
4390 | for I := 0 to 2 do |
||
4391 | begin |
||
4392 | T := K[0] + B; |
||
4393 | T := T shl K[16] or T shr (32 - K[16]); |
||
4394 | A := A xor (Cast128_Data[0, T shr 24] xor |
||
4395 | Cast128_Data[1, T shr 16 and $FF] - |
||
4396 | Cast128_Data[2, T shr 8 and $FF] + |
||
4397 | Cast128_Data[3, T and $FF]); |
||
4398 | T := K[1] xor A; |
||
4399 | T := T shl K[17] or T shr (32 - K[17]); |
||
4400 | B := B xor (Cast128_Data[0, T shr 24] - |
||
4401 | Cast128_Data[1, T shr 16 and $FF] + |
||
4402 | Cast128_Data[2, T shr 8 and $FF] xor |
||
4403 | Cast128_Data[3, T and $FF]); |
||
4404 | T := K[2] - B; |
||
4405 | T := T shl K[18] or T shr (32 - K[18]); |
||
4406 | A := A xor (Cast128_Data[0, T shr 24] + |
||
4407 | Cast128_Data[1, T shr 16 and $FF] xor |
||
4408 | Cast128_Data[2, T shr 8 and $FF] - |
||
4409 | Cast128_Data[3, T and $FF]); |
||
4410 | T := K[3] + A; |
||
4411 | T := T shl K[19] or T shr (32 - K[19]); |
||
4412 | B := B xor (Cast128_Data[0, T shr 24] xor |
||
4413 | Cast128_Data[1, T shr 16 and $FF] - |
||
4414 | Cast128_Data[2, T shr 8 and $FF] + |
||
4415 | Cast128_Data[3, T and $FF]); |
||
4416 | if I = 2 then Break; |
||
4417 | T := K[4] xor B; |
||
4418 | T := T shl K[20] or T shr (32 - K[20]); |
||
4419 | A := A xor (Cast128_Data[0, T shr 24] - |
||
4420 | Cast128_Data[1, T shr 16 and $FF] + |
||
4421 | Cast128_Data[2, T shr 8 and $FF] xor |
||
4422 | Cast128_Data[3, T and $FF]); |
||
4423 | T := K[5] - A; |
||
4424 | T := T shl K[21] or T shr (32 - K[21]); |
||
4425 | B := B xor (Cast128_Data[0, T shr 24] + |
||
4426 | Cast128_Data[1, T shr 16 and $FF] xor |
||
4427 | Cast128_Data[2, T shr 8 and $FF] - |
||
4428 | Cast128_Data[3, T and $FF]); |
||
4429 | if (I = 1) and (FRounds <= 12) then Break; |
||
4430 | K := @K[6]; |
||
4431 | end; |
||
4432 | PLongArray(Dest)[0] := SwapLong(B); |
||
4433 | PLongArray(Dest)[1] := SwapLong(A); |
||
4434 | end; |
||
4435 | |||
4436 | procedure TCipher_Cast128.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
4437 | var |
||
4438 | T,I,A,B: LongWord; |
||
4439 | K: PLongArray; |
||
4440 | label |
||
4441 | Start; |
||
4442 | begin |
||
4443 | Assert(Size = Context.BufferSize); |
||
4444 | |||
4445 | K := @PLongArray(FUser)[12]; |
||
4446 | B := SwapLong(PLongArray(Source)[0]); |
||
4447 | A := SwapLong(PLongArray(Source)[1]); |
||
4448 | I := 2; |
||
4449 | if FRounds <= 12 then Dec(PLongWord(K), 6) |
||
4450 | else goto Start; |
||
4451 | while I > 0 do |
||
4452 | begin |
||
4453 | Dec(I); |
||
4454 | T := K[5] - A; |
||
4455 | T := T shl K[21] or T shr (32 - K[21]); |
||
4456 | B := B xor (Cast128_Data[0, T shr 24] + |
||
4457 | Cast128_Data[1, T shr 16 and $FF] xor |
||
4458 | Cast128_Data[2, T shr 8 and $FF] - |
||
4459 | Cast128_Data[3, T and $FF]); |
||
4460 | T := K[4] xor B; |
||
4461 | T := T shl K[20] or T shr (32 - K[20]); |
||
4462 | A := A xor (Cast128_Data[0, T shr 24] - |
||
4463 | Cast128_Data[1, T shr 16 and $FF] + |
||
4464 | Cast128_Data[2, T shr 8 and $FF] xor |
||
4465 | Cast128_Data[3, T and $FF]); |
||
4466 | Start: |
||
4467 | T := K[3] + A; |
||
4468 | T := T shl K[19] or T shr (32 - K[19]); |
||
4469 | B := B xor (Cast128_Data[0, T shr 24] xor |
||
4470 | Cast128_Data[1, T shr 16 and $FF] - |
||
4471 | Cast128_Data[2, T shr 8 and $FF] + |
||
4472 | Cast128_Data[3, T and $FF]); |
||
4473 | T := K[2] - B; |
||
4474 | T := T shl K[18] or T shr (32 - K[18]); |
||
4475 | A := A xor (Cast128_Data[0, T shr 24] + |
||
4476 | Cast128_Data[1, T shr 16 and $FF] xor |
||
4477 | Cast128_Data[2, T shr 8 and $FF] - |
||
4478 | Cast128_Data[3, T and $FF]); |
||
4479 | T := K[1] xor A; |
||
4480 | T := T shl K[17] or T shr (32 - K[17]); |
||
4481 | B := B xor (Cast128_Data[0, T shr 24] - |
||
4482 | Cast128_Data[1, T shr 16 and $FF] + |
||
4483 | Cast128_Data[2, T shr 8 and $FF] xor |
||
4484 | Cast128_Data[3, T and $FF]); |
||
4485 | T := K[0] + B; |
||
4486 | T := T shl K[16] or T shr (32 - K[16]); |
||
4487 | A := A xor (Cast128_Data[0, T shr 24] xor |
||
4488 | Cast128_Data[1, T shr 16 and $FF] - |
||
4489 | Cast128_Data[2, T shr 8 and $FF] + |
||
4490 | Cast128_Data[3, T and $FF]); |
||
4491 | Dec(PLongWord(K), 6); |
||
4492 | end; |
||
4493 | PLongArray(Dest)[0] := SwapLong(A); |
||
4494 | PLongArray(Dest)[1] := SwapLong(B); |
||
4495 | end; |
||
4496 | |||
4497 | // .TCipher_Gost |
||
4498 | class function TCipher_Gost.Context: TCipherContext; |
||
4499 | begin |
||
4500 | Result.KeySize := 32; |
||
4501 | Result.BlockSize := 8; |
||
4502 | Result.BufferSize := 8; |
||
4503 | Result.UserSize := 32; |
||
4504 | Result.UserSave := False; |
||
4505 | end; |
||
4506 | |||
4507 | procedure TCipher_Gost.DoInit(const Key; Size: Integer); |
||
4508 | begin |
||
4509 | Move(Key, FUser^, Size); |
||
4510 | end; |
||
4511 | |||
4512 | procedure TCipher_Gost.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
4513 | var |
||
4514 | I,A,B,T: LongWord; |
||
4515 | K: PLongArray; |
||
4516 | begin |
||
4517 | Assert(Size = Context.BufferSize); |
||
4518 | |||
4519 | K := FUser; |
||
4520 | A := PLongArray(Source)[0]; |
||
4521 | B := PLongArray(Source)[1]; |
||
4522 | for I := 0 to 11 do |
||
4523 | begin |
||
4524 | if I and 3 = 0 then K := FUser; |
||
4525 | T := A + K[0]; |
||
4526 | B := B xor Gost_Data[0, T and $FF] xor |
||
4527 | Gost_Data[1, T shr 8 and $FF] xor |
||
4528 | Gost_Data[2, T shr 16 and $FF] xor |
||
4529 | Gost_Data[3, T shr 24 ]; |
||
4530 | T := B + K[1]; |
||
4531 | A := A xor Gost_Data[0, T and $FF] xor |
||
4532 | Gost_Data[1, T shr 8 and $FF] xor |
||
4533 | Gost_Data[2, T shr 16 and $FF] xor |
||
4534 | Gost_Data[3, T shr 24 ]; |
||
4535 | K := @K[2]; |
||
4536 | end; |
||
4537 | K := @PLongArray(FUser)[6]; |
||
4538 | for I := 0 to 3 do |
||
4539 | begin |
||
4540 | T := A + K[1]; |
||
4541 | B := B xor Gost_Data[0, T and $FF] xor |
||
4542 | Gost_Data[1, T shr 8 and $FF] xor |
||
4543 | Gost_Data[2, T shr 16 and $FF] xor |
||
4544 | Gost_Data[3, T shr 24 ]; |
||
4545 | T := B + K[0]; |
||
4546 | A := A xor Gost_Data[0, T and $FF] xor |
||
4547 | Gost_Data[1, T shr 8 and $FF] xor |
||
4548 | Gost_Data[2, T shr 16 and $FF] xor |
||
4549 | Gost_Data[3, T shr 24 ]; |
||
4550 | Dec(PLongWord(K), 2); |
||
4551 | end; |
||
4552 | PLongArray(Dest)[0] := B; |
||
4553 | PLongArray(Dest)[1] := A; |
||
4554 | end; |
||
4555 | |||
4556 | procedure TCipher_Gost.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
4557 | var |
||
4558 | I,A,B,T: LongWord; |
||
4559 | K: PLongArray; |
||
4560 | begin |
||
4561 | Assert(Size = Context.BufferSize); |
||
4562 | |||
4563 | A := PLongArray(Source)[0]; |
||
4564 | B := PLongArray(Source)[1]; |
||
4565 | K := FUser; |
||
4566 | for I := 0 to 3 do |
||
4567 | begin |
||
4568 | T := A + K[0]; |
||
4569 | B := B xor Gost_Data[0, T and $FF] xor |
||
4570 | Gost_Data[1, T shr 8 and $FF] xor |
||
4571 | Gost_Data[2, T shr 16 and $FF] xor |
||
4572 | Gost_Data[3, T shr 24]; |
||
4573 | T := B + K[1]; |
||
4574 | A := A xor Gost_Data[0, T and $FF] xor |
||
4575 | Gost_Data[1, T shr 8 and $FF] xor |
||
4576 | Gost_Data[2, T shr 16 and $FF] xor |
||
4577 | Gost_Data[3, T shr 24]; |
||
4578 | K := @K[2]; |
||
4579 | end; |
||
4580 | for I := 0 to 11 do |
||
4581 | begin |
||
4582 | if I and 3 = 0 then K := @PLongArray(FUser)[6]; |
||
4583 | T := A + K[1]; |
||
4584 | B := B xor Gost_Data[0, T and $FF] xor |
||
4585 | Gost_Data[1, T shr 8 and $FF] xor |
||
4586 | Gost_Data[2, T shr 16 and $FF] xor |
||
4587 | Gost_Data[3, T shr 24]; |
||
4588 | T := B + K[0]; |
||
4589 | A := A xor Gost_Data[0, T and $FF] xor |
||
4590 | Gost_Data[1, T shr 8 and $FF] xor |
||
4591 | Gost_Data[2, T shr 16 and $FF] xor |
||
4592 | Gost_Data[3, T shr 24]; |
||
4593 | Dec(PLongWord(K), 2); |
||
4594 | end; |
||
4595 | PLongArray(Dest)[0] := B; |
||
4596 | PLongArray(Dest)[1] := A; |
||
4597 | end; |
||
4598 | |||
4599 | // .TCipher_Misty |
||
4600 | class function TCipher_Misty.Context: TCipherContext; |
||
4601 | begin |
||
4602 | Result.KeySize := 16; |
||
4603 | Result.BlockSize := 8; |
||
4604 | Result.BufferSize := 8; |
||
4605 | Result.UserSize := 128; |
||
4606 | Result.UserSave := False; |
||
4607 | end; |
||
4608 | |||
4609 | function Misty_I(Value, Key: LongWord): LongWord; |
||
4610 | begin |
||
4611 | Result := Misty_Data9[Value shr 7 and $1FF] xor (Value and $7F); |
||
4612 | Value := (Misty_Data7[Value and $7F] xor Result and $7F) xor (Key shr 9 and $7F); |
||
4613 | Result := Misty_Data9[Result xor (Key and $1FF)] xor Value or Value shl 9; |
||
4614 | end; |
||
4615 | |||
4616 | function Misty_O(Value, K: LongWord; Key: PLongArray): LongWord; |
||
4617 | begin |
||
4618 | Result := Misty_I((Value shr 16) xor Key[K], Key[(K + 5) and 7 + 8]) xor (Value and $FFFF); |
||
4619 | Value := Misty_I((Value and $FFFF) xor Key[(K + 2) and 7], Key[(K + 1) and 7 + 8]) xor Result; |
||
4620 | Result := Misty_I(Result xor Key[(K + 7) and 7], Key[(K + 3) and 7 + 8]) xor Value; |
||
4621 | Result := Result or (Value xor Key[(k+4) and 7]) shl 16; |
||
4622 | end; |
||
4623 | |||
4624 | function Misty_E(Value, K: LongWord; Key: PLongArray): LongWord; |
||
4625 | begin |
||
4626 | Result := Value shr 16; |
||
4627 | Value := Value and $FFFF; |
||
4628 | if K and 1 <> 0 then |
||
4629 | begin |
||
4630 | K := K shr 1; |
||
4631 | Value := Value xor (Result and Key[(K + 2) and 7 + 8]); |
||
4632 | Result := Result xor (Value or Key[(K + 4) and 7]); |
||
4633 | end else |
||
4634 | begin |
||
4635 | K := K shr 1; |
||
4636 | Value := Value xor (Result and Key[K]); |
||
4637 | Result := Result xor (Value or Key[(K + 6) and 7 + 8]); |
||
4638 | end; |
||
4639 | Result:= (Result shl 16) or Value; |
||
4640 | end; |
||
4641 | |||
4642 | function Misty_D(Value, K: LongWord; Key: PLongArray): LongWord; |
||
4643 | begin |
||
4644 | Result := Value shr 16; |
||
4645 | Value := Value and $FFFF; |
||
4646 | if K and 1 <> 0 then |
||
4647 | begin |
||
4648 | K := K shr 1; |
||
4649 | Result := Result xor (Value or Key[(K + 4) and 7]); |
||
4650 | Value := Value xor (Result and Key[(K + 2) and 7 + 8]); |
||
4651 | end else |
||
4652 | begin |
||
4653 | K := K shr 1; |
||
4654 | Result := Result xor (Value or Key[(K +6) and 7 + 8]); |
||
4655 | Value := Value xor (Result and Key[K]); |
||
4656 | end; |
||
4657 | Result:= (Result shl 16) or Value; |
||
4658 | end; |
||
4659 | |||
4660 | procedure TCipher_Misty.DoInit(const Key; Size: Integer); |
||
4661 | var |
||
4662 | K: array[0..15] of Byte; |
||
4663 | D: PLongArray; |
||
4664 | I: Integer; |
||
4665 | begin |
||
4666 | FillChar(K, SizeOf(K), 0); |
||
4667 | Move(Key, K, Size); |
||
4668 | D := FUser; |
||
4669 | for I := 0 to 7 do |
||
4670 | D[I] := K[I * 2] * 256 + K[I * 2 +1]; |
||
4671 | for I := 0 to 7 do |
||
4672 | begin |
||
4673 | D[I + 8] := Misty_I(D[I], D[(I + 1) and 7]); |
||
4674 | D[I + 16] := D[I + 8] and $1FF; |
||
4675 | D[I + 24] := D[I + 8] shr 9; |
||
4676 | end; |
||
4677 | ProtectBuffer(K, SizeOf(K)); |
||
4678 | end; |
||
4679 | |||
4680 | procedure TCipher_Misty.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
4681 | var |
||
4682 | A,B: LongWord; |
||
4683 | begin |
||
4684 | Assert(Size = Context.BufferSize); |
||
4685 | |||
4686 | A := PLongArray(Source)[0]; |
||
4687 | B := PLongArray(Source)[1]; |
||
4688 | A := Misty_E(A, 0, FUser); |
||
4689 | B := Misty_E(B, 1, FUser) xor Misty_O(A, 0, FUser); |
||
4690 | A := A xor Misty_O(B, 1, FUser); |
||
4691 | A := Misty_E(A, 2, FUser); |
||
4692 | B := Misty_E(B, 3, FUser) xor Misty_O(A, 2, FUser); |
||
4693 | A := A xor Misty_O(B, 3, FUser); |
||
4694 | A := Misty_E(A, 4, FUser); |
||
4695 | B := Misty_E(B, 5, FUser) xor Misty_O(A, 4, FUser); |
||
4696 | A := A xor Misty_O(B, 5, FUser); |
||
4697 | A := Misty_E(A, 6, FUser); |
||
4698 | B := Misty_E(B, 7, FUser) xor Misty_O(A, 6, FUser); |
||
4699 | A := A xor Misty_O(B, 7, FUser); |
||
4700 | PLongArray(Dest)[0] := Misty_E(B, 9, FUser); |
||
4701 | PLongArray(Dest)[1] := Misty_E(A, 8, FUser); |
||
4702 | end; |
||
4703 | |||
4704 | procedure TCipher_Misty.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
4705 | var |
||
4706 | A,B: LongWord; |
||
4707 | begin |
||
4708 | Assert(Size = Context.BufferSize); |
||
4709 | |||
4710 | B := Misty_D(PLongArray(Source)[0], 9, FUser); |
||
4711 | A := Misty_D(PLongArray(Source)[1], 8, FUser); |
||
4712 | A := A xor Misty_O(B, 7, FUser); |
||
4713 | B := Misty_D(B xor Misty_O(A, 6, FUser), 7, FUser); |
||
4714 | A := Misty_D(A, 6, FUser); |
||
4715 | A := A xor Misty_O(B, 5, FUser); |
||
4716 | B := Misty_D(B xor Misty_O(A, 4, FUser), 5, FUser); |
||
4717 | A := Misty_D(A, 4, FUser); |
||
4718 | A := A xor Misty_O(B, 3, FUser); |
||
4719 | B := Misty_D(B xor Misty_O(A, 2, FUser), 3, FUser); |
||
4720 | A := Misty_D(A, 2, FUser); |
||
4721 | A := A xor Misty_O(B, 1, FUser); |
||
4722 | PLongArray(Dest)[0] := Misty_D(A, 0, FUser); |
||
4723 | PLongArray(Dest)[1] := Misty_D(B xor Misty_O(A, 0, FUser), 1, FUser); |
||
4724 | end; |
||
4725 | |||
4726 | // .TCipher_NewDES |
||
4727 | class function TCipher_NewDES.Context: TCipherContext; |
||
4728 | begin |
||
4729 | Result.KeySize := 15; |
||
4730 | Result.BlockSize := 8; |
||
4731 | Result.BufferSize := 8; |
||
4732 | Result.UserSize := 60 * 2; |
||
4733 | Result.UserSave := True; |
||
4734 | end; |
||
4735 | |||
4736 | procedure TCipher_NewDES.DoInit(const Key; Size: Integer); |
||
4737 | var |
||
4738 | K: array[0..14] of Byte; |
||
4739 | E: PByteArray; |
||
4740 | I: Integer; |
||
4741 | begin |
||
4742 | FillChar(K, SizeOf(K), 0); |
||
4743 | Move(Key, K, Size); |
||
4744 | E := FUser; |
||
4745 | Move(K, E[ 0], 15); |
||
4746 | Move(K, E[15], 15); |
||
4747 | Move(K, E[30], 15); |
||
4748 | Move(K, E[45], 15); |
||
4749 | E := @E[60]; |
||
4750 | I := 11; |
||
4751 | repeat |
||
4752 | E[0] := K[I]; I := (I +1) mod 15; |
||
4753 | E[1] := K[I]; I := (I +1) mod 15; |
||
4754 | E[2] := K[I]; I := (I +1) mod 15; |
||
4755 | E[3] := K[I]; I := (I +9) mod 15; |
||
4756 | if I = 12 then Break; |
||
4757 | E[4] := K[I]; Inc(I); |
||
4758 | E[5] := K[I]; Inc(I); |
||
4759 | E[6] := K[I]; I := (I + 9) mod 15; |
||
4760 | E := @E[7]; |
||
4761 | until False; |
||
4762 | ProtectBuffer(K, SizeOf(K)); |
||
4763 | end; |
||
4764 | |||
4765 | procedure NewDES_Func(Source, Dest, Key: PByteArray); |
||
4766 | var |
||
4767 | I: Integer; |
||
4768 | A,B,C,D,E,F,G,H: Byte; |
||
4769 | begin |
||
4770 | A := Source[0]; |
||
4771 | B := Source[1]; |
||
4772 | C := Source[2]; |
||
4773 | D := Source[3]; |
||
4774 | E := Source[4]; |
||
4775 | F := Source[5]; |
||
4776 | G := Source[6]; |
||
4777 | H := Source[7]; |
||
4778 | for I := 0 to 7 do |
||
4779 | begin |
||
4780 | E := E xor NewDES_Data[A xor Key[0]]; |
||
4781 | F := F xor NewDES_Data[B xor Key[1]]; |
||
4782 | G := G xor NewDES_Data[C xor Key[2]]; |
||
4783 | H := H xor NewDES_Data[D xor Key[3]]; |
||
4784 | B := B xor NewDES_Data[E xor Key[4]]; |
||
4785 | C := C xor NewDES_Data[F xor E]; |
||
4786 | D := D xor NewDES_Data[G xor Key[5]]; |
||
4787 | A := A xor NewDES_Data[H xor Key[6]]; |
||
4788 | Key := @Key[7]; |
||
4789 | end; |
||
4790 | E := E xor NewDES_Data[A xor Key[0]]; |
||
4791 | F := F xor NewDES_Data[B xor Key[1]]; |
||
4792 | G := G xor NewDES_Data[C xor Key[2]]; |
||
4793 | H := H xor NewDES_Data[D xor Key[3]]; |
||
4794 | Dest[0] := A; |
||
4795 | Dest[1] := B; |
||
4796 | Dest[2] := C; |
||
4797 | Dest[3] := D; |
||
4798 | Dest[4] := E; |
||
4799 | Dest[5] := F; |
||
4800 | Dest[6] := G; |
||
4801 | Dest[7] := H; |
||
4802 | end; |
||
4803 | |||
4804 | procedure TCipher_NewDES.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
4805 | begin |
||
4806 | Assert(Size = Context.BufferSize); |
||
4807 | NewDES_Func(Source, Dest, FUser); |
||
4808 | end; |
||
4809 | |||
4810 | procedure TCipher_NewDES.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
4811 | begin |
||
4812 | Assert(Size = Context.BufferSize); |
||
4813 | NewDES_Func(Source, Dest, @PByteArray(FUser)[60]); |
||
4814 | end; |
||
4815 | |||
4816 | // .TCipher_Q128 |
||
4817 | class function TCipher_Q128.Context: TCipherContext; |
||
4818 | begin |
||
4819 | Result.KeySize := 16; |
||
4820 | Result.BlockSize := 16; |
||
4821 | Result.BufferSize := 16; |
||
4822 | Result.UserSize := 256; |
||
4823 | Result.UserSave := False; |
||
4824 | end; |
||
4825 | |||
4826 | procedure TCipher_Q128.DoInit(const Key; Size: Integer); |
||
4827 | var |
||
4828 | K: array[0..3] of LongWord; |
||
4829 | D: PLongArray; |
||
4830 | I: Integer; |
||
4831 | begin |
||
4832 | FillChar(K, SizeOf(K), 0); |
||
4833 | Move(Key, K, Size); |
||
4834 | D := FUser; |
||
4835 | for I := 19 downto 1 do |
||
4836 | begin |
||
4837 | K[1] := K[1] xor Q128_Data[K[0] and $03FF]; K[0] := K[0] shr 10 or K[0] shl 22; |
||
4838 | K[2] := K[2] xor Q128_Data[K[1] and $03FF]; K[1] := K[1] shr 10 or K[1] shl 22; |
||
4839 | K[3] := K[3] xor Q128_Data[K[2] and $03FF]; K[2] := K[2] shr 10 or K[2] shl 22; |
||
4840 | K[0] := K[0] xor Q128_Data[K[3] and $03FF]; K[3] := K[3] shr 10 or K[3] shl 22; |
||
4841 | if I <= 16 then |
||
4842 | begin |
||
4843 | D[0] := K[0]; |
||
4844 | D[1] := K[1]; |
||
4845 | D[2] := K[2]; |
||
4846 | D[3] := K[3]; |
||
4847 | D := @D[4]; |
||
4848 | end; |
||
4849 | end; |
||
4850 | ProtectBuffer(K, SizeOf(K)); |
||
4851 | end; |
||
4852 | |||
4853 | procedure TCipher_Q128.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
4854 | {$IFDEF UseASM} |
||
4855 | asm |
||
4856 | PUSH ESI |
||
4857 | PUSH EDI |
||
4858 | PUSH EBX |
||
4859 | PUSH EBP |
||
4860 | PUSH ECX |
||
4861 | MOV EDI,[EAX].TCipher_Q128.FUser |
||
4862 | MOV EAX,[EDX + 0] // B0 |
||
4863 | MOV EBX,[EDX + 4] // B1 |
||
4864 | MOV ECX,[EDX + 8] // B2 |
||
4865 | MOV EDX,[EDX + 12] // B3 |
||
4866 | MOV EBP,16 |
||
4867 | @@1: MOV ESI,EAX |
||
4868 | ROL ESI,10 |
||
4869 | AND EAX,03FFh |
||
4870 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4871 | ADD EAX,[EDI + 0] |
||
4872 | XOR EAX,EBX |
||
4873 | MOV EBX,EAX |
||
4874 | ROL EBX,10 |
||
4875 | AND EAX,03FFh |
||
4876 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4877 | ADD EAX,[EDI + 4] |
||
4878 | XOR EAX,ECX |
||
4879 | MOV ECX,EAX |
||
4880 | ROL ECX,10 |
||
4881 | AND EAX,03FFh |
||
4882 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4883 | ADD EAX,[EDI + 8] |
||
4884 | XOR EAX,EDX |
||
4885 | MOV EDX,EAX |
||
4886 | ROL EDX,10 |
||
4887 | AND EAX,03FFh |
||
4888 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4889 | ADD EAX,[EDI + 12] |
||
4890 | XOR EAX,ESI |
||
4891 | DEC EBP |
||
4892 | LEA EDI,[EDI + 16] |
||
4893 | JNZ @@1 |
||
4894 | POP ESI |
||
4895 | MOV [ESI + 0],EAX // B0 |
||
4896 | MOV [ESI + 4],EBX // B1 |
||
4897 | MOV [ESI + 8],ECX // B2 |
||
4898 | MOV [ESI + 12],EDX // B3 |
||
4899 | POP EBP |
||
4900 | POP EBX |
||
4901 | POP EDI |
||
4902 | POP ESI |
||
4903 | end; |
||
4904 | {$ELSE} |
||
4905 | var |
||
4906 | D: PLongArray; |
||
4907 | B0,B1,B2,B3,I: LongWord; |
||
4908 | begin |
||
4909 | Assert(Size = Context.BufferSize); |
||
4910 | |||
4911 | D := FUser; |
||
4912 | B0 := PLongArray(Source)[0]; |
||
4913 | B1 := PLongArray(Source)[1]; |
||
4914 | B2 := PLongArray(Source)[2]; |
||
4915 | B3 := PLongArray(Source)[3]; |
||
4916 | for I := 0 to 15 do |
||
4917 | begin |
||
4918 | B1 := B1 xor (Q128_Data[B0 and $03FF] + D[0]); B0 := B0 shl 10 or B0 shr 22; |
||
4919 | B2 := B2 xor (Q128_Data[B1 and $03FF] + D[1]); B1 := B1 shl 10 or B1 shr 22; |
||
4920 | B3 := B3 xor (Q128_Data[B2 and $03FF] + D[2]); B2 := B2 shl 10 or B2 shr 22; |
||
4921 | B0 := B0 xor (Q128_Data[B3 and $03FF] + D[3]); B3 := B3 shl 10 or B3 shr 22; |
||
4922 | D := @D[4]; |
||
4923 | end; |
||
4924 | PLongArray(Dest)[0] := B0; |
||
4925 | PLongArray(Dest)[1] := B1; |
||
4926 | PLongArray(Dest)[2] := B2; |
||
4927 | PLongArray(Dest)[3] := B3; |
||
4928 | end; |
||
4929 | {$ENDIF} |
||
4930 | |||
4931 | procedure TCipher_Q128.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
4932 | {$IFDEF UseASM} |
||
4933 | asm |
||
4934 | PUSH ESI |
||
4935 | PUSH EDI |
||
4936 | PUSH EBX |
||
4937 | PUSH EBP |
||
4938 | PUSH ECX |
||
4939 | MOV EDI,[EAX].TCipher_Q128.FUser |
||
4940 | LEA EDI,[EDI + 64 * 4] |
||
4941 | MOV ESI,[EDX + 0] // B0 |
||
4942 | MOV EBX,[EDX + 4] // B1 |
||
4943 | MOV ECX,[EDX + 8] // B2 |
||
4944 | MOV EDX,[EDX + 12] // B3 |
||
4945 | MOV EBP,16 |
||
4946 | @@1: SUB EDI,16 |
||
4947 | ROR EDX,10 |
||
4948 | MOV EAX,EDX |
||
4949 | AND EAX,03FFh |
||
4950 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4951 | ADD EAX,[EDI + 12] |
||
4952 | XOR ESI,EAX |
||
4953 | ROR ECX,10 |
||
4954 | MOV EAX,ECX |
||
4955 | AND EAX,03FFh |
||
4956 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4957 | ADD EAX,[EDI + 8] |
||
4958 | XOR EDX,EAX |
||
4959 | ROR EBX,10 |
||
4960 | MOV EAX,EBX |
||
4961 | AND EAX,03FFh |
||
4962 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4963 | ADD EAX,[EDI + 4] |
||
4964 | XOR ECX,EAX |
||
4965 | ROR ESI,10 |
||
4966 | MOV EAX,ESI |
||
4967 | AND EAX,03FFh |
||
4968 | MOV EAX,[EAX * 4 + OFFSET Q128_DATA] |
||
4969 | ADD EAX,[EDI] |
||
4970 | XOR EBX,EAX |
||
4971 | DEC EBP |
||
4972 | JNZ @@1 |
||
4973 | POP EAX |
||
4974 | MOV [EAX + 0],ESI // B0 |
||
4975 | MOV [EAX + 4],EBX // B1 |
||
4976 | MOV [EAX + 8],ECX // B2 |
||
4977 | MOV [EAX + 12],EDX // B3 |
||
4978 | POP EBP |
||
4979 | POP EBX |
||
4980 | POP EDI |
||
4981 | POP ESI |
||
4982 | end; |
||
4983 | {$ELSE} |
||
4984 | var |
||
4985 | D: PLongArray; |
||
4986 | B0,B1,B2,B3,I: LongWord; |
||
4987 | begin |
||
4988 | Assert(Size = Context.BufferSize); |
||
4989 | |||
4990 | D := @PLongArray(FUser)[60]; |
||
4991 | B0 := PLongArray(Source)[0]; |
||
4992 | B1 := PLongArray(Source)[1]; |
||
4993 | B2 := PLongArray(Source)[2]; |
||
4994 | B3 := PLongArray(Source)[3]; |
||
4995 | for I := 0 to 15 do |
||
4996 | begin |
||
4997 | B3 := B3 shr 10 or B3 shl 22; B0 := B0 xor (Q128_Data[B3 and $03FF] + D[3]); |
||
4998 | B2 := B2 shr 10 or B2 shl 22; B3 := B3 xor (Q128_Data[B2 and $03FF] + D[2]); |
||
4999 | B1 := B1 shr 10 or B1 shl 22; B2 := B2 xor (Q128_Data[B1 and $03FF] + D[1]); |
||
5000 | B0 := B0 shr 10 or B0 shl 22; B1 := B1 xor (Q128_Data[B0 and $03FF] + D[0]); |
||
5001 | Dec(PLongWord(D), 4); |
||
5002 | end; |
||
5003 | PLongArray(Dest)[0] := B0; |
||
5004 | PLongArray(Dest)[1] := B1; |
||
5005 | PLongArray(Dest)[2] := B2; |
||
5006 | PLongArray(Dest)[3] := B3; |
||
5007 | end; |
||
5008 | {$ENDIF} |
||
5009 | |||
5010 | // .TCipher_RC2 |
||
5011 | class function TCipher_RC2.Context: TCipherContext; |
||
5012 | begin |
||
5013 | Result.KeySize := 128; |
||
5014 | Result.BlockSize := 8; |
||
5015 | Result.BufferSize := 8; |
||
5016 | Result.UserSize := 128; |
||
5017 | Result.UserSave := False; |
||
5018 | end; |
||
5019 | |||
5020 | procedure TCipher_RC2.DoInit(const Key; Size: Integer); |
||
5021 | // New keysheduling according to RFC2268 and its testcases. |
||
5022 | // the v3.0 keysetup was an older, bad version |
||
5023 | // special thanks goes to Brendan Bosnan to pointing me out that. |
||
5024 | var |
||
5025 | I,L,Mask,KeyEffectiveBits: Integer; |
||
5026 | K: PByteArray; |
||
5027 | begin |
||
5028 | if Size <= 0 then Exit; |
||
5029 | KeyEffectiveBits := Size * 8; |
||
5030 | L := KeyEffectiveBits and 7; |
||
5031 | if L = 0 then Mask := $FF |
||
5032 | else Mask := $FF shr (8 - L); |
||
5033 | L := (KeyEffectiveBits + 7) shr 3; |
||
5034 | K := FUser; |
||
5035 | Move(Key, K[0], Size); |
||
5036 | for I := Size to 127 do |
||
5037 | K[I] := RC2_Data[(K[I - Size] + K[I - 1]) and $FF]; |
||
5038 | K[128 - L] := RC2_Data[K[128 - L] and Mask]; |
||
5039 | for I := 127 - L downto 0 do |
||
5040 | K[I] := RC2_Data[K[I + 1] xor K[I + L]]; |
||
5041 | end; |
||
5042 | |||
5043 | procedure TCipher_RC2.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
5044 | var |
||
5045 | I: Integer; |
||
5046 | K: PWordArray; |
||
5047 | A,B,C,D: Word; |
||
5048 | begin |
||
5049 | Assert(Size = Context.BufferSize); |
||
5050 | |||
5051 | K := FUser; |
||
5052 | A := PWordArray(Source)[0]; |
||
5053 | B := PWordArray(Source)[1]; |
||
5054 | C := PWordArray(Source)[2]; |
||
5055 | D := PWordArray(Source)[3]; |
||
5056 | for I := 0 to 15 do |
||
5057 | begin |
||
5058 | Inc(A, (B and not D) + (C and D) + K[I * 4 +0]); A := A shl 1 or A shr 15; |
||
5059 | Inc(B, (C and not A) + (D and A) + K[I * 4 +1]); B := B shl 2 or B shr 14; |
||
5060 | Inc(C, (D and not B) + (A and B) + K[I * 4 +2]); C := C shl 3 or C shr 13; |
||
5061 | Inc(D, (A and not C) + (B and C) + K[I * 4 +3]); D := D shl 5 or D shr 11; |
||
5062 | if I in [4, 10] then |
||
5063 | begin |
||
5064 | Inc(A, K[D and $3F]); |
||
5065 | Inc(B, K[A and $3F]); |
||
5066 | Inc(C, K[B and $3F]); |
||
5067 | Inc(D, K[C and $3F]); |
||
5068 | end; |
||
5069 | end; |
||
5070 | PWordArray(Dest)[0] := A; |
||
5071 | PWordArray(Dest)[1] := B; |
||
5072 | PWordArray(Dest)[2] := C; |
||
5073 | PWordArray(Dest)[3] := D; |
||
5074 | end; |
||
5075 | |||
5076 | procedure TCipher_RC2.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
5077 | var |
||
5078 | I: Integer; |
||
5079 | K: PWordArray; |
||
5080 | A,B,C,D: Word; |
||
5081 | begin |
||
5082 | Assert(Size = Context.BlockSize); |
||
5083 | |||
5084 | K := FUser; |
||
5085 | A := PWordArray(Source)[0]; |
||
5086 | B := PWordArray(Source)[1]; |
||
5087 | C := PWordArray(Source)[2]; |
||
5088 | D := PWordArray(Source)[3]; |
||
5089 | for I := 15 downto 0 do |
||
5090 | begin |
||
5091 | D := D shr 5 or D shl 11 - (A and not C) - (B and C) - K[I * 4 +3]; |
||
5092 | C := C shr 3 or C shl 13 - (D and not B) - (A and B) - K[I * 4 +2]; |
||
5093 | B := B shr 2 or B shl 14 - (C and not A) - (D and A) - K[I * 4 +1]; |
||
5094 | A := A shr 1 or A shl 15 - (B and not D) - (C and D) - K[I * 4 +0]; |
||
5095 | if I in [5, 11] then |
||
5096 | begin |
||
5097 | Dec(D, K[C and $3F]); |
||
5098 | Dec(C, K[B and $3F]); |
||
5099 | Dec(B, K[A and $3F]); |
||
5100 | Dec(A, K[D and $3F]); |
||
5101 | end; |
||
5102 | end; |
||
5103 | PWordArray(Dest)[0] := A; |
||
5104 | PWordArray(Dest)[1] := B; |
||
5105 | PWordArray(Dest)[2] := C; |
||
5106 | PWordArray(Dest)[3] := D; |
||
5107 | end; |
||
5108 | |||
5109 | // .TCipher_RC5 |
||
5110 | class function TCipher_RC5.Context: TCipherContext; |
||
5111 | begin |
||
5112 | Result.KeySize := 256; |
||
5113 | Result.BlockSize := 8; |
||
5114 | Result.BufferSize := 8; |
||
5115 | Result.UserSize := 136; |
||
5116 | Result.UserSave := False; |
||
5117 | end; |
||
5118 | |||
5119 | procedure TCipher_RC5.SetRounds(Value: Integer); |
||
5120 | begin |
||
5121 | if Value <> FRounds then |
||
5122 | begin |
||
5123 | if not (FState in [csNew, csInitialized, csDone]) then Done; |
||
5124 | if Value <= 0 then Value := 12; |
||
5125 | FRounds := Value; |
||
5126 | end; |
||
5127 | end; |
||
5128 | |||
5129 | procedure TCipher_RC5.DoInit(const Key; Size: Integer); |
||
5130 | var |
||
5131 | K: array[0..63] of LongWord; |
||
5132 | L,Z,I,J: Integer; |
||
5133 | D: PLongArray; |
||
5134 | A,B,T: LongWord; |
||
5135 | begin |
||
5136 | if FRounds <= 0 then FRounds := 12; |
||
5137 | FillChar(K, SizeOf(K), 0); |
||
5138 | Move(Key, K, Size); |
||
5139 | D := FUser; |
||
5140 | L := (Size +3) shr 2; |
||
5141 | if L <= 0 then L := 1; |
||
5142 | T := $B7E15163; |
||
5143 | for I := 0 to (FRounds + 1) * 2 do |
||
5144 | begin |
||
5145 | D[I] := T; |
||
5146 | Inc(T, $9E3779B9); |
||
5147 | end; |
||
5148 | if L > (FRounds + 1) * 2 then Z := L * 3 |
||
5149 | else Z := (FRounds + 1) * 6; |
||
5150 | I := 0; |
||
5151 | J := 0; |
||
5152 | A := 0; |
||
5153 | B := 0; |
||
5154 | for Z := Z downto 1 do |
||
5155 | begin |
||
5156 | A := D[I] + A + B; |
||
5157 | A := A shl 3 or A shr 29; |
||
5158 | D[I] := A; |
||
5159 | T := A + B; |
||
5160 | B := K[J] + T; |
||
5161 | B := B shl T or B shr (32 - T); |
||
5162 | K[J] := B; |
||
5163 | I := (I + 1) mod ((FRounds + 1) * 2); |
||
5164 | J := (J + 1) mod L; |
||
5165 | end; |
||
5166 | ProtectBuffer(K, SizeOf(K)); |
||
5167 | end; |
||
5168 | |||
5169 | procedure TCipher_RC5.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
5170 | var |
||
5171 | K: PLongArray; |
||
5172 | I: Integer; |
||
5173 | A,B: LongWord; |
||
5174 | begin |
||
5175 | Assert(Size = Context.BufferSize); |
||
5176 | |||
5177 | K := FUser; |
||
5178 | A := PLongArray(Source)[0] + K[0]; |
||
5179 | B := PLongArray(Source)[1] + K[1]; |
||
5180 | for I := 1 to FRounds do |
||
5181 | begin |
||
5182 | A := A xor B; A := A shl B or A shr (32 - B) + K[I * 2 +0]; |
||
5183 | B := B xor A; B := B shl A or B shr (32 - A) + K[I * 2 +1]; |
||
5184 | end; |
||
5185 | PLongArray(Dest)[0] := A; |
||
5186 | PLongArray(Dest)[1] := B; |
||
5187 | end; |
||
5188 | |||
5189 | procedure TCipher_RC5.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
5190 | var |
||
5191 | K: PLongArray; |
||
5192 | I: Integer; |
||
5193 | A,B: LongWord; |
||
5194 | begin |
||
5195 | Assert(Size = Context.BufferSize); |
||
5196 | |||
5197 | K := @PLongArray(FUser)[0]; |
||
5198 | A := PLongArray(Source)[0]; |
||
5199 | B := PLongArray(Source)[1]; |
||
5200 | for I := FRounds downto 1 do |
||
5201 | begin |
||
5202 | B := B - K[I * 2 +1]; B := B shr A or B shl (32 - A) xor A; |
||
5203 | A := A - K[I * 2 +0]; A := A shr B or A shl (32 - B) xor B; |
||
5204 | end; |
||
5205 | PLongArray(Dest)[0] := A - K[0]; |
||
5206 | PLongArray(Dest)[1] := B - K[1]; |
||
5207 | end; |
||
5208 | |||
5209 | // .TCipher_SAFER |
||
5210 | class function TCipher_SAFER.Context: TCipherContext; |
||
5211 | begin |
||
5212 | Result.KeySize := 16; |
||
5213 | Result.BlockSize := 8; |
||
5214 | Result.BufferSize := 8; |
||
5215 | Result.UserSize := 768; |
||
5216 | Result.UserSave := False; |
||
5217 | end; |
||
5218 | |||
5219 | procedure TCipher_SAFER.SetRounds(Value: Integer); |
||
5220 | begin |
||
5221 | if not (FState in [csNew, csInitialized, csDone]) then Done; |
||
5222 | if (Value < 4) or (Value > 13) then |
||
5223 | case FVersion of {Default Rounds} |
||
5224 | svK40, svSK40: Value := 5; |
||
5225 | svK64, svSK64: Value := 6; |
||
5226 | svK128, svSK128: Value := 10; |
||
5227 | else |
||
5228 | Value := 8; |
||
5229 | end; |
||
5230 | FRounds := Value; |
||
5231 | end; |
||
5232 | |||
5233 | procedure TCipher_SAFER.SetVersion(Value: TSAFERVersion); |
||
5234 | begin |
||
5235 | if Value <> FVersion then |
||
5236 | begin |
||
5237 | if not (FState in [csNew, csInitialized, csDone]) then Done; |
||
5238 | FVersion := Value; |
||
5239 | SetRounds(0); |
||
5240 | end; |
||
5241 | end; |
||
5242 | |||
5243 | procedure TCipher_SAFER.DoInit(const Key; Size: Integer); |
||
5244 | |||
5245 | procedure InitTab; |
||
5246 | var |
||
5247 | I,E: Integer; |
||
5248 | Exp: PByteArray; |
||
5249 | Log: PByteArray; |
||
5250 | begin |
||
5251 | Exp := FUser; |
||
5252 | Log := @Exp[256]; |
||
5253 | E := 1; |
||
5254 | for I := 0 to 255 do |
||
5255 | begin |
||
5256 | Exp[I] := E and $FF; |
||
5257 | Log[E and $FF] := I; |
||
5258 | E := (E * 45) mod 257; |
||
5259 | end; |
||
5260 | end; |
||
5261 | |||
5262 | procedure InitKey; |
||
5263 | var |
||
5264 | D: PByte; |
||
5265 | Exp: PByteArray; |
||
5266 | Strong: Boolean; |
||
5267 | K: array[Boolean, 0..8] of Byte; |
||
5268 | I,J: Integer; |
||
5269 | begin |
||
5270 | Strong := FVersion in [svSK40, svSK64, svSK128]; |
||
5271 | Exp := FUser; |
||
5272 | D := @Exp[512]; |
||
5273 | FillChar(K, SizeOf(K), 0); |
||
5274 | {Setup Key A} |
||
5275 | I := Size; |
||
5276 | if I > 8 then I := 8; |
||
5277 | Move(Key, K[False], I); |
||
5278 | {Setup the Key for K-40, SK-40} |
||
5279 | if FVersion in [svK40, svSK40] then |
||
5280 | begin |
||
5281 | K[False, 5] := K[False, 0] xor K[False, 2] xor 129; |
||
5282 | K[False, 6] := K[False, 0] xor K[False, 3] xor K[False, 4] xor 66; |
||
5283 | K[False, 7] := K[False, 1] xor K[False, 2] xor K[False, 4] xor 36; |
||
5284 | K[False, 8] := K[False, 1] xor K[False, 3] xor 24; |
||
5285 | Move(K[False], K[True], SizeOf(K[False])); |
||
5286 | end else |
||
5287 | begin |
||
5288 | if Size > 8 then |
||
5289 | begin |
||
5290 | I := Size - 8; |
||
5291 | if I > 8 then I := 8; |
||
5292 | Move(TByteArray(Key)[8], K[True], I); |
||
5293 | end else Move(K[False], K[True], 9); |
||
5294 | for I := 0 to 7 do |
||
5295 | begin |
||
5296 | K[False, 8] := K[False, 8] xor K[False, I]; |
||
5297 | K[True, 8] := K[True, 8] xor K[True, I]; |
||
5298 | end; |
||
5299 | end; |
||
5300 | {Setup the KeyData} |
||
5301 | Move(K[True], D^, 8); |
||
5302 | Inc(D, 8); |
||
5303 | |||
5304 | for I := 0 to 8 do |
||
5305 | K[False, I] := K[False, I] shr 3 or K[False, I] shl 5; |
||
5306 | |||
5307 | for I := 1 to FRounds do |
||
5308 | begin |
||
5309 | for J := 0 to 8 do |
||
5310 | begin |
||
5311 | K[False, J] := K[False, J] shl 6 or K[False, J] shr 2; |
||
5312 | K[True, J] := K[True, J] shl 6 or K[True, J] shr 2; |
||
5313 | end; |
||
5314 | for J := 0 to 7 do |
||
5315 | begin |
||
5316 | if Strong then D^ := K[False, (J + I * 2 -1) mod 9] + Exp[Exp[18 * I + J +1]] |
||
5317 | else D^ := K[False, J] + Exp[Exp[18 * I + J +1]]; |
||
5318 | Inc(D); |
||
5319 | end; |
||
5320 | for J := 0 to 7 do |
||
5321 | begin |
||
5322 | if Strong then D^ := K[True, (J + I * 2) mod 9] + Exp[Exp[18 * I + J +10]] |
||
5323 | else D^ := K[True, J] + Exp[Exp[18 * I + J +10]]; |
||
5324 | Inc(D); |
||
5325 | end; |
||
5326 | end; |
||
5327 | ProtectBuffer(K, SizeOf(K)); |
||
5328 | end; |
||
5329 | |||
5330 | begin |
||
5331 | if (FRounds < 4) or (FRounds > 13) then |
||
5332 | case FVersion of |
||
5333 | svK40, svSK40: FRounds := 5; |
||
5334 | svK64, svSK64: FRounds := 6; |
||
5335 | svK128, svSK128: FRounds := 10; |
||
5336 | else |
||
5337 | FRounds := 8; |
||
5338 | end; |
||
5339 | InitTab; |
||
5340 | InitKey; |
||
5341 | end; |
||
5342 | |||
5343 | procedure TCipher_SAFER.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
5344 | var |
||
5345 | Exp,Log,Key: PByteArray; |
||
5346 | I: Integer; |
||
5347 | A,B,C,D,E,F,G,H,T: Byte; |
||
5348 | begin |
||
5349 | Assert(Size = Context.BufferSize); |
||
5350 | |||
5351 | Exp := FUser; |
||
5352 | Log := @Exp[256]; |
||
5353 | Key := @Exp[512]; |
||
5354 | A := PByteArray(Source)[0]; |
||
5355 | B := PByteArray(Source)[1]; |
||
5356 | C := PByteArray(Source)[2]; |
||
5357 | D := PByteArray(Source)[3]; |
||
5358 | E := PByteArray(Source)[4]; |
||
5359 | F := PByteArray(Source)[5]; |
||
5360 | G := PByteArray(Source)[6]; |
||
5361 | H := PByteArray(Source)[7]; |
||
5362 | for I := 0 to FRounds -1 do |
||
5363 | begin |
||
5364 | A := A xor Key[0]; |
||
5365 | B := B + Key[1]; |
||
5366 | C := C + Key[2]; |
||
5367 | D := D xor Key[3]; |
||
5368 | E := E xor Key[4]; |
||
5369 | F := F + Key[5]; |
||
5370 | G := G + Key[6]; |
||
5371 | H := H xor Key[7]; |
||
5372 | A := Exp[A] + Key[8]; |
||
5373 | B := Log[B] xor Key[9]; |
||
5374 | C := Log[C] xor Key[10]; |
||
5375 | D := Exp[D] + Key[11]; |
||
5376 | E := Exp[E] + Key[12]; |
||
5377 | F := Log[F] xor Key[13]; |
||
5378 | G := Log[G] xor Key[14]; |
||
5379 | H := Exp[H] + Key[15]; |
||
5380 | Inc(B, A); Inc(A, B); |
||
5381 | Inc(D, C); Inc(C, D); |
||
5382 | Inc(F, E); Inc(E, F); |
||
5383 | Inc(H, G); Inc(G, H); |
||
5384 | Inc(C, A); Inc(A, C); |
||
5385 | Inc(G, E); Inc(E, G); |
||
5386 | Inc(D, B); Inc(B, D); |
||
5387 | Inc(H, F); Inc(F, H); |
||
5388 | Inc(E, A); Inc(A, E); |
||
5389 | Inc(F, B); Inc(B, F); |
||
5390 | Inc(G, C); Inc(C, G); |
||
5391 | Inc(H, D); Inc(D, H); |
||
5392 | T := B; B := E; E := C; C := T; |
||
5393 | T := D; D := F; F := G; G := T; |
||
5394 | Key := @Key[16]; |
||
5395 | end; |
||
5396 | PByteArray(Dest)[0] := A xor Key[0]; |
||
5397 | PByteArray(Dest)[1] := B + Key[1]; |
||
5398 | PByteArray(Dest)[2] := C + Key[2]; |
||
5399 | PByteArray(Dest)[3] := D xor Key[3]; |
||
5400 | PByteArray(Dest)[4] := E xor Key[4]; |
||
5401 | PByteArray(Dest)[5] := F + Key[5]; |
||
5402 | PByteArray(Dest)[6] := G + Key[6]; |
||
5403 | PByteArray(Dest)[7] := H xor Key[7]; |
||
5404 | end; |
||
5405 | |||
5406 | procedure TCipher_SAFER.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
5407 | var |
||
5408 | Exp,Log,Key: PByteArray; |
||
5409 | I: Integer; |
||
5410 | A,B,C,D,E,F,G,H,T: Byte; |
||
5411 | begin |
||
5412 | Assert(Size = Context.BufferSize); |
||
5413 | |||
5414 | Exp := FUser; |
||
5415 | Log := @Exp[256]; |
||
5416 | Key := @Exp[504 + 8 * (FRounds * 2 + 1)]; |
||
5417 | A := PByteArray(Source)[0] xor Key[0]; |
||
5418 | B := PByteArray(Source)[1] - Key[1]; |
||
5419 | C := PByteArray(Source)[2] - Key[2]; |
||
5420 | D := PByteArray(Source)[3] xor Key[3]; |
||
5421 | E := PByteArray(Source)[4] xor Key[4]; |
||
5422 | F := PByteArray(Source)[5] - Key[5]; |
||
5423 | G := PByteArray(Source)[6] - Key[6]; |
||
5424 | H := PByteArray(Source)[7] xor Key[7]; |
||
5425 | for I := 0 to FRounds -1 do |
||
5426 | begin |
||
5427 | Dec(PByte(Key), 16); |
||
5428 | T := E; E := B; B := C; C := T; |
||
5429 | T := F; F := D; D := G; G := T; |
||
5430 | Dec(A, E); Dec(E, A); |
||
5431 | Dec(B, F); Dec(F, B); |
||
5432 | Dec(C, G); Dec(G, C); |
||
5433 | Dec(D, H); Dec(H, D); |
||
5434 | Dec(A, C); Dec(C, A); |
||
5435 | Dec(E, G); Dec(G, E); |
||
5436 | Dec(B, D); Dec(D, B); |
||
5437 | Dec(F, H); Dec(H, F); |
||
5438 | Dec(A, B); Dec(B, A); |
||
5439 | Dec(C, D); Dec(D, C); |
||
5440 | Dec(E, F); Dec(F, E); |
||
5441 | Dec(G, H); Dec(H, G); |
||
5442 | H := H - Key[15]; |
||
5443 | G := G xor Key[14]; |
||
5444 | F := F xor Key[13]; |
||
5445 | E := E - Key[12]; |
||
5446 | D := D - Key[11]; |
||
5447 | C := C xor Key[10]; |
||
5448 | B := B xor Key[9]; |
||
5449 | A := A - Key[8]; |
||
5450 | H := Log[H] xor Key[7]; |
||
5451 | G := Exp[G] - Key[6]; |
||
5452 | F := Exp[F] - Key[5]; |
||
5453 | E := Log[E] xor Key[4]; |
||
5454 | D := Log[D] xor Key[3]; |
||
5455 | C := Exp[C] - Key[2]; |
||
5456 | B := Exp[B] - Key[1]; |
||
5457 | A := Log[A] xor Key[0]; |
||
5458 | end; |
||
5459 | PByteArray(Dest)[0] := A; |
||
5460 | PByteArray(Dest)[1] := B; |
||
5461 | PByteArray(Dest)[2] := C; |
||
5462 | PByteArray(Dest)[3] := D; |
||
5463 | PByteArray(Dest)[4] := E; |
||
5464 | PByteArray(Dest)[5] := F; |
||
5465 | PByteArray(Dest)[6] := G; |
||
5466 | PByteArray(Dest)[7] := H; |
||
5467 | end; |
||
5468 | |||
5469 | // .TCipher_Shark |
||
5470 | type |
||
5471 | PLong64 = ^TLong64; |
||
5472 | TLong64 = packed record |
||
5473 | L,R: LongWord; |
||
5474 | end; |
||
5475 | |||
5476 | PLong64Array = ^TLong64Array; |
||
5477 | TLong64Array = array[0..1023] of TLong64; |
||
5478 | |||
5479 | class function TCipher_Shark.Context: TCipherContext; |
||
5480 | begin |
||
5481 | Result.KeySize := 16; |
||
5482 | Result.BlockSize := 8; |
||
5483 | Result.BufferSize := 8; |
||
5484 | Result.UserSize := 112; |
||
5485 | Result.UserSave := False; |
||
5486 | end; |
||
5487 | |||
5488 | procedure TCipher_Shark.DoInit(const Key; Size: Integer); |
||
5489 | var |
||
5490 | Log, ALog: array[0..255] of Byte; |
||
5491 | |||
5492 | procedure InitLog; |
||
5493 | var |
||
5494 | I, J: Word; |
||
5495 | begin |
||
5496 | ALog[0] := 1; |
||
5497 | for I := 1 to 255 do |
||
5498 | begin |
||
5499 | J := ALog[I-1] shl 1; |
||
5500 | if J and $100 <> 0 then J := J xor $01F5; |
||
5501 | ALog[I] := J; |
||
5502 | end; |
||
5503 | for I := 1 to 254 do Log[ALog[I]] := I; |
||
5504 | end; |
||
5505 | |||
5506 | function Transform(A: TLong64): TLong64; |
||
5507 | |||
5508 | function Mul(A, B: Integer): Byte; |
||
5509 | begin |
||
5510 | Result := ALog[(Log[A] + Log[B]) mod 255]; |
||
5511 | end; |
||
5512 | |||
5513 | var |
||
5514 | I,J: Byte; |
||
5515 | K,T: array[0..7] of Byte; |
||
5516 | begin |
||
5517 | Move(A.R, K[0], 4); |
||
5518 | Move(A.L, K[4], 4); |
||
5519 | SwapLongBuffer(K, K, 2); |
||
5520 | for I := 0 to 7 do |
||
5521 | begin |
||
5522 | T[I] := Mul(Shark_I[I, 0], K[0]); |
||
5523 | for J := 1 to 7 do T[I] := T[I] xor Mul(Shark_I[I, J], K[J]); |
||
5524 | end; |
||
5525 | Result.L := T[0]; |
||
5526 | Result.R := 0; |
||
5527 | for I := 1 to 7 do |
||
5528 | begin |
||
5529 | Result.R := Result.R shl 8 or Result.L shr 24; |
||
5530 | Result.L := Result.L shl 8 xor T[I]; |
||
5531 | end; |
||
5532 | end; |
||
5533 | |||
5534 | function Shark(D: TLong64; K: PLong64): TLong64; |
||
5535 | var |
||
5536 | R,T: Integer; |
||
5537 | begin |
||
5538 | for R := 0 to 4 do |
||
5539 | begin |
||
5540 | D.L := D.L xor K.L; |
||
5541 | D.R := D.R xor K.R; |
||
5542 | Inc(K); |
||
5543 | T := Shark_CE[0, D.R shr 23 and $1FE] xor |
||
5544 | Shark_CE[1, D.R shr 15 and $1FE] xor |
||
5545 | Shark_CE[2, D.R shr 7 and $1FE] xor |
||
5546 | Shark_CE[3, D.R shl 1 and $1FE] xor |
||
5547 | Shark_CE[4, D.L shr 23 and $1FE] xor |
||
5548 | Shark_CE[5, D.L shr 15 and $1FE] xor |
||
5549 | Shark_CE[6, D.L shr 7 and $1FE] xor |
||
5550 | Shark_CE[7, D.L shl 1 and $1FE]; |
||
5551 | |||
5552 | D.R := Shark_CE[0, D.R shr 23 and $1FE or 1] xor |
||
5553 | Shark_CE[1, D.R shr 15 and $1FE or 1] xor |
||
5554 | Shark_CE[2, D.R shr 7 and $1FE or 1] xor |
||
5555 | Shark_CE[3, D.R shl 1 and $1FE or 1] xor |
||
5556 | Shark_CE[4, D.L shr 23 and $1FE or 1] xor |
||
5557 | Shark_CE[5, D.L shr 15 and $1FE or 1] xor |
||
5558 | Shark_CE[6, D.L shr 7 and $1FE or 1] xor |
||
5559 | Shark_CE[7, D.L shl 1 and $1FE or 1]; |
||
5560 | D.L := T; |
||
5561 | end; |
||
5562 | D.L := D.L xor K.L; |
||
5563 | D.R := D.R xor K.R; |
||
5564 | Inc(K); |
||
5565 | D.L := LongWord(Shark_SE[D.L shr 24 and $FF]) shl 24 xor |
||
5566 | LongWord(Shark_SE[D.L shr 16 and $FF]) shl 16 xor |
||
5567 | LongWord(Shark_SE[D.L shr 8 and $FF]) shl 8 xor |
||
5568 | LongWord(Shark_SE[D.L and $FF]); |
||
5569 | D.R := LongWord(Shark_SE[D.R shr 24 and $FF]) shl 24 xor |
||
5570 | LongWord(Shark_SE[D.R shr 16 and $FF]) shl 16 xor |
||
5571 | LongWord(Shark_SE[D.R shr 8 and $FF]) shl 8 xor |
||
5572 | LongWord(Shark_SE[D.R and $FF]); |
||
5573 | Result.L := D.L xor K.L; |
||
5574 | Result.R := D.R xor K.R; |
||
5575 | end; |
||
5576 | |||
5577 | var |
||
5578 | T: array[0..6] of TLong64; |
||
5579 | A: array[0..6] of TLong64; |
||
5580 | K: array[0..15] of Byte; |
||
5581 | I,J,R: Byte; |
||
5582 | E,D: PLong64Array; |
||
5583 | L: TLong64; |
||
5584 | begin |
||
5585 | FillChar(K, SizeOf(K), 0); |
||
5586 | Move(Key, K, Size); |
||
5587 | InitLog; |
||
5588 | E := FUser; |
||
5589 | D := @E[7]; |
||
5590 | Move(Shark_CE[0], T, SizeOf(T)); |
||
5591 | T[6] := Transform(T[6]); |
||
5592 | I := 0; |
||
5593 | for R := 0 to 6 do |
||
5594 | begin |
||
5595 | Inc(I); |
||
5596 | A[R].L := K[I and $F]; |
||
5597 | A[R].R := 0; |
||
5598 | for J := 1 to 7 do |
||
5599 | begin |
||
5600 | Inc(I); |
||
5601 | A[R].R := A[R].R shl 8 or A[R].L shr 24; |
||
5602 | A[R].L := A[R].L shl 8 or K[I and $F]; |
||
5603 | end; |
||
5604 | end; |
||
5605 | L.L := 0; |
||
5606 | L.R := 0; |
||
5607 | L := Shark(L, @T); |
||
5608 | E[0].L := A[0].L xor L.L; |
||
5609 | E[0].R := A[0].R xor L.R; |
||
5610 | for R := 1 to 6 do |
||
5611 | begin |
||
5612 | L := Shark(E[R - 1], @T); |
||
5613 | E[R].L := A[R].L xor L.L; |
||
5614 | E[R].R := A[R].R xor L.R; |
||
5615 | end; |
||
5616 | E[6] := Transform(E[6]); |
||
5617 | D[0] := E[6]; |
||
5618 | D[6] := E[0]; |
||
5619 | for R := 1 to 5 do |
||
5620 | D[R] := Transform(E[6-R]); |
||
5621 | ProtectBuffer(Log, SizeOf(Log)); |
||
5622 | ProtectBuffer(ALog, SizeOf(ALog)); |
||
5623 | ProtectBuffer(T, SizeOf(T)); |
||
5624 | ProtectBuffer(A, SizeOf(A)); |
||
5625 | ProtectBuffer(K, SizeOf(K)); |
||
5626 | end; |
||
5627 | |||
5628 | procedure TCipher_Shark.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
5629 | var |
||
5630 | I: Integer; |
||
5631 | T,L,R: LongWord; |
||
5632 | K: PLongArray; |
||
5633 | begin |
||
5634 | Assert(Size = Context.BufferSize); |
||
5635 | |||
5636 | K := FUser; |
||
5637 | L := PLong64(Source).L; |
||
5638 | R := PLong64(Source).R; |
||
5639 | for I := 0 to 4 do |
||
5640 | begin |
||
5641 | L := L xor K[I * 2 +0]; |
||
5642 | R := R xor K[I * 2 +1]; |
||
5643 | T := Shark_CE[0, R shr 23 and $1FE] xor |
||
5644 | Shark_CE[1, R shr 15 and $1FE] xor |
||
5645 | Shark_CE[2, R shr 7 and $1FE] xor |
||
5646 | Shark_CE[3, R shl 1 and $1FE] xor |
||
5647 | Shark_CE[4, L shr 23 and $1FE] xor |
||
5648 | Shark_CE[5, L shr 15 and $1FE] xor |
||
5649 | Shark_CE[6, L shr 7 and $1FE] xor |
||
5650 | Shark_CE[7, L shl 1 and $1FE]; |
||
5651 | R := Shark_CE[0, R shr 23 and $1FE or 1] xor |
||
5652 | Shark_CE[1, R shr 15 and $1FE or 1] xor |
||
5653 | Shark_CE[2, R shr 7 and $1FE or 1] xor |
||
5654 | Shark_CE[3, R shl 1 and $1FE or 1] xor |
||
5655 | Shark_CE[4, L shr 23 and $1FE or 1] xor |
||
5656 | Shark_CE[5, L shr 15 and $1FE or 1] xor |
||
5657 | Shark_CE[6, L shr 7 and $1FE or 1] xor |
||
5658 | Shark_CE[7, L shl 1 and $1FE or 1]; |
||
5659 | L := T; |
||
5660 | end; |
||
5661 | L := L xor K[10]; |
||
5662 | R := R xor K[11]; |
||
5663 | L := LongWord(Shark_SE[L shr 24 ]) shl 24 xor |
||
5664 | LongWord(Shark_SE[L shr 16 and $FF]) shl 16 xor |
||
5665 | LongWord(Shark_SE[L shr 8 and $FF]) shl 8 xor |
||
5666 | LongWord(Shark_SE[L and $FF]); |
||
5667 | R := LongWord(Shark_SE[R shr 24 ]) shl 24 xor |
||
5668 | LongWord(Shark_SE[R shr 16 and $FF]) shl 16 xor |
||
5669 | LongWord(Shark_SE[R shr 8 and $FF]) shl 8 xor |
||
5670 | LongWord(Shark_SE[R and $FF]); |
||
5671 | PLong64(Dest).L := L xor K[12]; |
||
5672 | PLong64(Dest).R := R xor K[13]; |
||
5673 | end; |
||
5674 | |||
5675 | procedure TCipher_Shark.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
5676 | var |
||
5677 | I: Integer; |
||
5678 | T,R,L: LongWord; |
||
5679 | K: PLongArray; |
||
5680 | begin |
||
5681 | Assert(Size = Context.BufferSize); |
||
5682 | |||
5683 | K := @PLongArray(FUser)[14]; |
||
5684 | L := PLong64(Source).L; |
||
5685 | R := PLong64(Source).R; |
||
5686 | for I := 0 to 4 do |
||
5687 | begin |
||
5688 | L := L xor K[I * 2 +0]; |
||
5689 | R := R xor K[I * 2 +1]; |
||
5690 | T := Shark_CD[0, R shr 23 and $1FE] xor |
||
5691 | Shark_CD[1, R shr 15 and $1FE] xor |
||
5692 | Shark_CD[2, R shr 7 and $1FE] xor |
||
5693 | Shark_CD[3, R shl 1 and $1FE] xor |
||
5694 | Shark_CD[4, L shr 23 and $1FE] xor |
||
5695 | Shark_CD[5, L shr 15 and $1FE] xor |
||
5696 | Shark_CD[6, L shr 7 and $1FE] xor |
||
5697 | Shark_CD[7, L shl 1 and $1FE]; |
||
5698 | R := Shark_CD[0, R shr 23 and $1FE or 1] xor |
||
5699 | Shark_CD[1, R shr 15 and $1FE or 1] xor |
||
5700 | Shark_CD[2, R shr 7 and $1FE or 1] xor |
||
5701 | Shark_CD[3, R shl 1 and $1FE or 1] xor |
||
5702 | Shark_CD[4, L shr 23 and $1FE or 1] xor |
||
5703 | Shark_CD[5, L shr 15 and $1FE or 1] xor |
||
5704 | Shark_CD[6, L shr 7 and $1FE or 1] xor |
||
5705 | Shark_CD[7, L shl 1 and $1FE or 1]; |
||
5706 | L := T; |
||
5707 | end; |
||
5708 | L := L xor K[10]; |
||
5709 | R := R xor K[11]; |
||
5710 | L := LongWord(Shark_SD[L shr 24 ]) shl 24 xor |
||
5711 | LongWord(Shark_SD[L shr 16 and $FF]) shl 16 xor |
||
5712 | LongWord(Shark_SD[L shr 8 and $FF]) shl 8 xor |
||
5713 | LongWord(Shark_SD[L and $FF]); |
||
5714 | R := LongWord(Shark_SD[R shr 24 ]) shl 24 xor |
||
5715 | LongWord(Shark_SD[R shr 16 and $FF]) shl 16 xor |
||
5716 | LongWord(Shark_SD[R shr 8 and $FF]) shl 8 xor |
||
5717 | LongWord(Shark_SD[R and $FF]); |
||
5718 | PLong64(Dest).L := L xor K[12]; |
||
5719 | PLong64(Dest).R := R xor K[13]; |
||
5720 | end; |
||
5721 | |||
5722 | |||
5723 | // .TCipher_Skipjack |
||
5724 | type |
||
5725 | PSkipjackTab = ^TSkipjackTab; |
||
5726 | TSkipjackTab = array[0..255] of Byte; |
||
5727 | |||
5728 | class function TCipher_Skipjack.Context: TCipherContext; |
||
5729 | begin |
||
5730 | Result.KeySize := 10; |
||
5731 | Result.BlockSize := 8; |
||
5732 | Result.BufferSize := 8; |
||
5733 | Result.UserSize := $A00; |
||
5734 | Result.UserSave := False; |
||
5735 | end; |
||
5736 | |||
5737 | procedure TCipher_Skipjack.DoInit(const Key; Size: Integer); |
||
5738 | var |
||
5739 | K: array[0..9] of Byte; |
||
5740 | D: PByte; |
||
5741 | I,J: Integer; |
||
5742 | begin |
||
5743 | FillChar(K, SizeOf(K), 0); |
||
5744 | Move(Key, K, Size); |
||
5745 | D := FUser; |
||
5746 | for I := 0 to 9 do |
||
5747 | for J := 0 to 255 do |
||
5748 | begin |
||
5749 | D^ := Skipjack_Data[J xor K[I]]; |
||
5750 | Inc(D); |
||
5751 | end; |
||
5752 | ProtectBuffer(K, SizeOf(K)); |
||
5753 | end; |
||
5754 | |||
5755 | procedure TCipher_Skipjack.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
5756 | var |
||
5757 | Tab,Min: PSkipjackTab; |
||
5758 | Max: PChar; |
||
5759 | K,T,A,B,C,D: LongWord; |
||
5760 | begin |
||
5761 | Assert(Size = Context.BufferSize); |
||
5762 | |||
5763 | Min := FUser; |
||
5764 | Max := PChar(Min) + 9 * 256; |
||
5765 | Tab := Min; |
||
5766 | A := Swap(PWordArray(Source)[0]); |
||
5767 | B := Swap(PWordArray(Source)[1]); |
||
5768 | C := Swap(PWordArray(Source)[2]); |
||
5769 | D := Swap(PWordArray(Source)[3]); |
||
5770 | K := 0; |
||
5771 | repeat |
||
5772 | Inc(K); |
||
5773 | T := A; |
||
5774 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5775 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5776 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5777 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5778 | A := T xor D xor K; |
||
5779 | D := C; |
||
5780 | C := B; |
||
5781 | B := T; |
||
5782 | until K = 8; |
||
5783 | repeat |
||
5784 | Inc(K); |
||
5785 | T := A; |
||
5786 | A := D; |
||
5787 | D := C; |
||
5788 | C := T xor B xor K; |
||
5789 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5790 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5791 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5792 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5793 | B := T; |
||
5794 | until K = 16; |
||
5795 | repeat |
||
5796 | Inc(K); |
||
5797 | T := A; |
||
5798 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5799 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5800 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5801 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5802 | A := T xor D xor K; |
||
5803 | D := C; |
||
5804 | C := B; |
||
5805 | B := T; |
||
5806 | until K = 24; |
||
5807 | repeat |
||
5808 | Inc(K); |
||
5809 | T := A; |
||
5810 | A := D; |
||
5811 | D := C; |
||
5812 | C := T xor B xor K; |
||
5813 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5814 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5815 | T := T xor Tab[T and $FF] shl 8; Inc(Tab); if Tab > Max then Tab := Min; |
||
5816 | T := T xor Tab[T shr 8]; Inc(Tab); if Tab > Max then Tab := Min; |
||
5817 | B := T; |
||
5818 | until K = 32; |
||
5819 | PWordArray(Dest)[0] := Swap(A); |
||
5820 | PWordArray(Dest)[1] := Swap(B); |
||
5821 | PWordArray(Dest)[2] := Swap(C); |
||
5822 | PWordArray(Dest)[3] := Swap(D); |
||
5823 | end; |
||
5824 | |||
5825 | procedure TCipher_Skipjack.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
5826 | var |
||
5827 | Tab,Max: PSkipjackTab; |
||
5828 | Min: PChar; |
||
5829 | K,T,A,B,C,D: LongWord; |
||
5830 | begin |
||
5831 | Assert(Size = Context.BufferSize); |
||
5832 | |||
5833 | Min := FUser; |
||
5834 | Max := Pointer(Min + 9 * 256); |
||
5835 | Tab := Pointer(Min + 7 * 256); |
||
5836 | A := Swap(PWordArray(Source)[0]); {holds as Integer, Compiler make faster Code} |
||
5837 | B := Swap(PWordArray(Source)[1]); |
||
5838 | C := Swap(PWordArray(Source)[2]); |
||
5839 | D := Swap(PWordArray(Source)[3]); |
||
5840 | K := 32; |
||
5841 | repeat |
||
5842 | T := B; |
||
5843 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5844 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5845 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5846 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5847 | B := T xor C xor K; |
||
5848 | C := D; |
||
5849 | D := A; |
||
5850 | A := T; |
||
5851 | Dec(K); |
||
5852 | until K = 24; |
||
5853 | repeat |
||
5854 | T := B; |
||
5855 | B := C; |
||
5856 | C := D; |
||
5857 | D := T xor A xor K; |
||
5858 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5859 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5860 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5861 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5862 | A := T; |
||
5863 | Dec(K); |
||
5864 | until K = 16; |
||
5865 | repeat |
||
5866 | T := B; |
||
5867 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5868 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5869 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5870 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5871 | B := C xor T xor K; |
||
5872 | C := D; |
||
5873 | D := A; |
||
5874 | A := T; |
||
5875 | Dec(K); |
||
5876 | until K = 8; |
||
5877 | repeat |
||
5878 | T := B; |
||
5879 | B := C; |
||
5880 | C := D; |
||
5881 | D := T xor A xor K; |
||
5882 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5883 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5884 | T := T xor Tab[T shr 8]; Dec(Tab); if Tab < Min then Tab := Max; |
||
5885 | T := T xor Tab[T and $FF] shl 8; Dec(Tab); if Tab < Min then Tab := Max; |
||
5886 | A := T; |
||
5887 | Dec(K); |
||
5888 | until K = 0; |
||
5889 | PWordArray(Dest)[0] := Swap(A); |
||
5890 | PWordArray(Dest)[1] := Swap(B); |
||
5891 | PWordArray(Dest)[2] := Swap(C); |
||
5892 | PWordArray(Dest)[3] := Swap(D); |
||
5893 | end; |
||
5894 | |||
5895 | |||
5896 | // .TCipher_TEA |
||
5897 | const |
||
5898 | TEA_Delta = $9E3779B9; |
||
5899 | |||
5900 | class function TCipher_TEA.Context: TCipherContext; |
||
5901 | begin |
||
5902 | Result.KeySize := 16; |
||
5903 | Result.BlockSize := 8; |
||
5904 | Result.BufferSize := 8; |
||
5905 | Result.UserSize := 32; |
||
5906 | Result.UserSave := False; |
||
5907 | end; |
||
5908 | |||
5909 | procedure TCipher_TEA.SetRounds(Value: Integer); |
||
5910 | begin |
||
5911 | if not (FState in [csNew, csInitialized, csDone]) then Done; |
||
5912 | if Value < 16 then Value := 16 else |
||
5913 | if Value > 32 then Value := 32; |
||
5914 | FRounds := Value; |
||
5915 | end; |
||
5916 | |||
5917 | procedure TCipher_TEA.DoInit(const Key; Size: Integer); |
||
5918 | begin |
||
5919 | Move(Key, FUser^, Size); |
||
5920 | SetRounds(FRounds); |
||
5921 | end; |
||
5922 | |||
5923 | procedure TCipher_TEA.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
5924 | var |
||
5925 | I: Integer; |
||
5926 | Sum,X,Y,A,B,C,D: LongWord; |
||
5927 | begin |
||
5928 | Assert(Size = Context.BufferSize); |
||
5929 | |||
5930 | Sum := 0; |
||
5931 | A := PLongArray(FUser)[0]; |
||
5932 | B := PLongArray(FUser)[1]; |
||
5933 | C := PLongArray(FUser)[2]; |
||
5934 | D := PLongArray(FUser)[3]; |
||
5935 | X := PLongArray(Source)[0]; |
||
5936 | Y := PLongArray(Source)[1]; |
||
5937 | for I := 0 to FRounds -1 do |
||
5938 | begin |
||
5939 | Inc(Sum, TEA_Delta); |
||
5940 | Inc(X, (((Y shl 4 + A) xor Y) + Sum) xor (Y shr 5 + B)); |
||
5941 | Inc(Y, (((X shl 4 + C) xor X) + Sum) xor (X shr 5 + D)); |
||
5942 | end; |
||
5943 | PLongArray(Dest)[0] := X; |
||
5944 | PLongArray(Dest)[1] := Y; |
||
5945 | end; |
||
5946 | |||
5947 | procedure TCipher_TEA.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
5948 | var |
||
5949 | I: Integer; |
||
5950 | Sum,X,Y,A,B,C,D: LongWord; |
||
5951 | begin |
||
5952 | Assert(Size = Context.BufferSize); |
||
5953 | |||
5954 | Sum := TEA_Delta * LongWord(FRounds); |
||
5955 | A := PLongArray(FUser)[0]; |
||
5956 | B := PLongArray(FUser)[1]; |
||
5957 | C := PLongArray(FUser)[2]; |
||
5958 | D := PLongArray(FUser)[3]; |
||
5959 | X := PLongArray(Source)[0]; |
||
5960 | Y := PLongArray(Source)[1]; |
||
5961 | for I := 0 to FRounds -1 do |
||
5962 | begin |
||
5963 | Dec(Y, (X shl 4 + C) xor X + Sum xor (X shr 5 + D)); |
||
5964 | Dec(X, (Y shl 4 + A) xor Y + Sum xor (Y shr 5 + B)); |
||
5965 | Dec(Sum, TEA_Delta); |
||
5966 | end; |
||
5967 | PLongArray(Dest)[0] := X; |
||
5968 | PLongArray(Dest)[1] := Y; |
||
5969 | end; |
||
5970 | |||
5971 | // .TCipher_TEAN |
||
5972 | procedure TCipher_TEAN.DoEncode(Source, Dest: Pointer; Size: Integer); |
||
5973 | var |
||
5974 | I,Sum,X,Y: LongWord; |
||
5975 | K: PLongArray; |
||
5976 | begin |
||
5977 | Assert(Size = Context.BufferSize); |
||
5978 | |||
5979 | Sum := 0; |
||
5980 | X := PLongArray(Source)[0]; |
||
5981 | Y := PLongArray(Source)[1]; |
||
5982 | K := FUser; |
||
5983 | for I := 0 to FRounds -1 do |
||
5984 | begin |
||
5985 | Inc(X, (Y shl 4 xor Y shr 5) + (Y xor Sum) + K[Sum and 3]); |
||
5986 | Inc(Sum, TEA_Delta); |
||
5987 | Inc(Y, (X shl 4 xor X shr 5) + (X xor Sum) + K[Sum shr 11 and 3]); |
||
5988 | end; |
||
5989 | PLongArray(Dest)[0] := X; |
||
5990 | PLongArray(Dest)[1] := Y; |
||
5991 | end; |
||
5992 | |||
5993 | procedure TCipher_TEAN.DoDecode(Source, Dest: Pointer; Size: Integer); |
||
5994 | var |
||
5995 | I: Integer; |
||
5996 | Sum,X,Y: LongWord; |
||
5997 | K: PLongArray; |
||
5998 | begin |
||
5999 | Assert(Size = Context.BufferSize); |
||
6000 | |||
6001 | Sum := TEA_Delta * LongWord(FRounds); |
||
6002 | X := PLongArray(Source)[0]; |
||
6003 | Y := PLongArray(Source)[1]; |
||
6004 | K := FUser; |
||
6005 | for I := 0 to FRounds -1 do |
||
6006 | begin |
||
6007 | Dec(Y, (X shl 4 xor X shr 5) + (X xor Sum) + K[Sum shr 11 and 3]); |
||
6008 | Dec(Sum, TEA_Delta); |
||
6009 | Dec(X, (Y shl 4 xor Y shr 5) + (Y xor Sum) + K[Sum and 3]); |
||
6010 | end; |
||
6011 | PLongArray(Dest)[0] := X; |
||
6012 | PLongArray(Dest)[1] := Y; |
||
6013 | end; |
||
6014 | |||
6015 | |||
6016 | end. |
||
6017 |