]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/OStatus/extlib/Crypt/Rijndael.php
is_a() with 3 params only supported in 5.3.9 anyway
[quix0rs-gnu-social.git] / plugins / OStatus / extlib / Crypt / Rijndael.php
1 <?php\r
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */\r
3 \r
4 /**\r
5  * Pure-PHP implementation of Rijndael.\r
6  *\r
7  * Does not use mcrypt, even when available, for reasons that are explained below.\r
8  *\r
9  * PHP versions 4 and 5\r
10  *\r
11  * If {@link Crypt_Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits.  If \r
12  * {@link Crypt_Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from \r
13  * {@link Crypt_Rijndael::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's \r
14  * 136-bits it'll be null-padded to 160-bits and 160 bits will be the key length until \r
15  * {@link Crypt_Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated.\r
16  *\r
17  * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length.  mcrypt, for example,\r
18  * does not.  AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.\r
19  * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the\r
20  * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224.  Indeed, 160 and 224\r
21  * are first defined as valid key / block lengths in \r
22  * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}: \r
23  * Extensions: Other block and Cipher Key lengths.\r
24  *\r
25  * {@internal The variable names are the same as those in \r
26  * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}\r
27  *\r
28  * Here's a short example of how to use this library:\r
29  * <code>\r
30  * <?php\r
31  *    include('Crypt/Rijndael.php');\r
32  *\r
33  *    $rijndael = new Crypt_Rijndael();\r
34  *\r
35  *    $rijndael->setKey('abcdefghijklmnop');\r
36  *\r
37  *    $size = 10 * 1024;\r
38  *    $plaintext = '';\r
39  *    for ($i = 0; $i < $size; $i++) {\r
40  *        $plaintext.= 'a';\r
41  *    }\r
42  *\r
43  *    echo $rijndael->decrypt($rijndael->encrypt($plaintext));\r
44  * ?>\r
45  * </code>\r
46  *\r
47  * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy\r
48  * of this software and associated documentation files (the "Software"), to deal\r
49  * in the Software without restriction, including without limitation the rights\r
50  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
51  * copies of the Software, and to permit persons to whom the Software is\r
52  * furnished to do so, subject to the following conditions:\r
53  * \r
54  * The above copyright notice and this permission notice shall be included in\r
55  * all copies or substantial portions of the Software.\r
56  * \r
57  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
58  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
59  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
60  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
61  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
62  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
63  * THE SOFTWARE.\r
64  *\r
65  * @category   Crypt\r
66  * @package    Crypt_Rijndael\r
67  * @author     Jim Wigginton <terrafrost@php.net>\r
68  * @copyright  MMVIII Jim Wigginton\r
69  * @license    http://www.opensource.org/licenses/mit-license.html  MIT License\r
70  * @link       http://phpseclib.sourceforge.net\r
71  */\r
72 \r
73 /**#@+\r
74  * @access public\r
75  * @see Crypt_Rijndael::encrypt()\r
76  * @see Crypt_Rijndael::decrypt()\r
77  */\r
78 /**\r
79  * Encrypt / decrypt using the Counter mode.\r
80  *\r
81  * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.\r
82  *\r
83  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29\r
84  */\r
85 define('CRYPT_RIJNDAEL_MODE_CTR', -1);\r
86 /**\r
87  * Encrypt / decrypt using the Electronic Code Book mode.\r
88  *\r
89  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29\r
90  */\r
91 define('CRYPT_RIJNDAEL_MODE_ECB', 1);\r
92 /**\r
93  * Encrypt / decrypt using the Code Book Chaining mode.\r
94  *\r
95  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29\r
96  */\r
97 define('CRYPT_RIJNDAEL_MODE_CBC', 2);\r
98 /**\r
99  * Encrypt / decrypt using the Cipher Feedback mode.\r
100  *\r
101  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29\r
102  */\r
103 define('CRYPT_RIJNDAEL_MODE_CFB', 3);\r
104 /**\r
105  * Encrypt / decrypt using the Cipher Feedback mode.\r
106  *\r
107  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29\r
108  */\r
109 define('CRYPT_RIJNDAEL_MODE_OFB', 4);\r
110 /**#@-*/\r
111 \r
112 /**#@+\r
113  * @access private\r
114  * @see Crypt_Rijndael::Crypt_Rijndael()\r
115  */\r
116 /**\r
117  * Toggles the internal implementation\r
118  */\r
119 define('CRYPT_RIJNDAEL_MODE_INTERNAL', 1);\r
120 /**\r
121  * Toggles the mcrypt implementation\r
122  */\r
123 define('CRYPT_RIJNDAEL_MODE_MCRYPT', 2);\r
124 /**#@-*/\r
125 \r
126 /**\r
127  * Pure-PHP implementation of Rijndael.\r
128  *\r
129  * @author  Jim Wigginton <terrafrost@php.net>\r
130  * @version 0.1.0\r
131  * @access  public\r
132  * @package Crypt_Rijndael\r
133  */\r
134 class Crypt_Rijndael {\r
135     /**\r
136      * The Encryption Mode\r
137      *\r
138      * @see Crypt_Rijndael::Crypt_Rijndael()\r
139      * @var Integer\r
140      * @access private\r
141      */\r
142     var $mode;\r
143 \r
144     /**\r
145      * The Key\r
146      *\r
147      * @see Crypt_Rijndael::setKey()\r
148      * @var String\r
149      * @access private\r
150      */\r
151     var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";\r
152 \r
153     /**\r
154      * The Initialization Vector\r
155      *\r
156      * @see Crypt_Rijndael::setIV()\r
157      * @var String\r
158      * @access private\r
159      */\r
160     var $iv = '';\r
161 \r
162     /**\r
163      * A "sliding" Initialization Vector\r
164      *\r
165      * @see Crypt_Rijndael::enableContinuousBuffer()\r
166      * @var String\r
167      * @access private\r
168      */\r
169     var $encryptIV = '';\r
170 \r
171     /**\r
172      * A "sliding" Initialization Vector\r
173      *\r
174      * @see Crypt_Rijndael::enableContinuousBuffer()\r
175      * @var String\r
176      * @access private\r
177      */\r
178     var $decryptIV = '';\r
179 \r
180     /**\r
181      * Continuous Buffer status\r
182      *\r
183      * @see Crypt_Rijndael::enableContinuousBuffer()\r
184      * @var Boolean\r
185      * @access private\r
186      */\r
187     var $continuousBuffer = false;\r
188 \r
189     /**\r
190      * Padding status\r
191      *\r
192      * @see Crypt_Rijndael::enablePadding()\r
193      * @var Boolean\r
194      * @access private\r
195      */\r
196     var $padding = true;\r
197 \r
198     /**\r
199      * Does the key schedule need to be (re)calculated?\r
200      *\r
201      * @see setKey()\r
202      * @see setBlockLength()\r
203      * @see setKeyLength()\r
204      * @var Boolean\r
205      * @access private\r
206      */\r
207     var $changed = true;\r
208 \r
209     /**\r
210      * Has the key length explicitly been set or should it be derived from the key, itself?\r
211      *\r
212      * @see setKeyLength()\r
213      * @var Boolean\r
214      * @access private\r
215      */\r
216     var $explicit_key_length = false;\r
217 \r
218     /**\r
219      * The Key Schedule\r
220      *\r
221      * @see _setup()\r
222      * @var Array\r
223      * @access private\r
224      */\r
225     var $w;\r
226 \r
227     /**\r
228      * The Inverse Key Schedule\r
229      *\r
230      * @see _setup()\r
231      * @var Array\r
232      * @access private\r
233      */\r
234     var $dw;\r
235 \r
236     /**\r
237      * The Block Length\r
238      *\r
239      * @see setBlockLength()\r
240      * @var Integer\r
241      * @access private\r
242      * @internal The max value is 32, the min value is 16.  All valid values are multiples of 4.  Exists in conjunction with\r
243      *     $Nb because we need this value and not $Nb to pad strings appropriately.  \r
244      */\r
245     var $block_size = 16;\r
246 \r
247     /**\r
248      * The Block Length divided by 32\r
249      *\r
250      * @see setBlockLength()\r
251      * @var Integer\r
252      * @access private\r
253      * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4.  Exists in conjunction with $block_size \r
254      *    because the encryption / decryption / key schedule creation requires this number and not $block_size.  We could \r
255      *    derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu\r
256      *    of that, we'll just precompute it once.\r
257      *\r
258      */\r
259     var $Nb = 4;\r
260 \r
261     /**\r
262      * The Key Length\r
263      *\r
264      * @see setKeyLength()\r
265      * @var Integer\r
266      * @access private\r
267      * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $key_size\r
268      *    because the encryption / decryption / key schedule creation requires this number and not $key_size.  We could \r
269      *    derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu\r
270      *    of that, we'll just precompute it once.\r
271      */\r
272     var $key_size = 16;\r
273 \r
274     /**\r
275      * The Key Length divided by 32\r
276      *\r
277      * @see setKeyLength()\r
278      * @var Integer\r
279      * @access private\r
280      * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4\r
281      */\r
282     var $Nk = 4;\r
283 \r
284     /**\r
285      * The Number of Rounds\r
286      *\r
287      * @var Integer\r
288      * @access private\r
289      * @internal The max value is 14, the min value is 10.\r
290      */\r
291     var $Nr;\r
292 \r
293     /**\r
294      * Shift offsets\r
295      *\r
296      * @var Array\r
297      * @access private\r
298      */\r
299     var $c;\r
300 \r
301     /**\r
302      * Precomputed mixColumns table\r
303      *\r
304      * @see Crypt_Rijndael()\r
305      * @var Array\r
306      * @access private\r
307      */\r
308     var $t0;\r
309 \r
310     /**\r
311      * Precomputed mixColumns table\r
312      *\r
313      * @see Crypt_Rijndael()\r
314      * @var Array\r
315      * @access private\r
316      */\r
317     var $t1;\r
318 \r
319     /**\r
320      * Precomputed mixColumns table\r
321      *\r
322      * @see Crypt_Rijndael()\r
323      * @var Array\r
324      * @access private\r
325      */\r
326     var $t2;\r
327 \r
328     /**\r
329      * Precomputed mixColumns table\r
330      *\r
331      * @see Crypt_Rijndael()\r
332      * @var Array\r
333      * @access private\r
334      */\r
335     var $t3;\r
336 \r
337     /**\r
338      * Precomputed invMixColumns table\r
339      *\r
340      * @see Crypt_Rijndael()\r
341      * @var Array\r
342      * @access private\r
343      */\r
344     var $dt0;\r
345 \r
346     /**\r
347      * Precomputed invMixColumns table\r
348      *\r
349      * @see Crypt_Rijndael()\r
350      * @var Array\r
351      * @access private\r
352      */\r
353     var $dt1;\r
354 \r
355     /**\r
356      * Precomputed invMixColumns table\r
357      *\r
358      * @see Crypt_Rijndael()\r
359      * @var Array\r
360      * @access private\r
361      */\r
362     var $dt2;\r
363 \r
364     /**\r
365      * Precomputed invMixColumns table\r
366      *\r
367      * @see Crypt_Rijndael()\r
368      * @var Array\r
369      * @access private\r
370      */\r
371     var $dt3;\r
372 \r
373     /**\r
374      * The SubByte S-Box\r
375      *\r
376      * @see Crypt_Rijndael::_encryptBlock()\r
377      * @var Array\r
378      * @access private\r
379      */\r
380     var $sbox;\r
381 \r
382     /**\r
383      * The inverse SubByte S-Box\r
384      *\r
385      * @see Crypt_Rijndael::_decryptBlock()\r
386      * @var Array\r
387      * @access private\r
388      */\r
389     var $isbox;\r
390 \r
391     /**\r
392      * Performance-optimized callback function for en/decrypt()\r
393      *\r
394      * @see Crypt_Rijndael::encrypt()\r
395      * @see Crypt_Rijndael::decrypt()\r
396      * @see Crypt_Rijndael::inline_crypt_setup()\r
397      * @see Crypt_Rijndael::$use_inline_crypt\r
398      * @var Callback\r
399      * @access private\r
400      */\r
401     var $inline_crypt;\r
402 \r
403     /**\r
404      * Holds whether performance-optimized $inline_crypt should be used or not.\r
405      *\r
406      * @see Crypt_Rijndael::Crypt_Rijndael()\r
407      * @see Crypt_Rijndael::inline_crypt_setup()\r
408      * @see Crypt_Rijndael::$inline_crypt\r
409      * @var Boolean\r
410      * @access private\r
411      */\r
412     var $use_inline_crypt = true;\r
413 \r
414     /**\r
415      * Is the mode one that is paddable?\r
416      *\r
417      * @see Crypt_Rijndael::Crypt_Rijndael()\r
418      * @var Boolean\r
419      * @access private\r
420      */\r
421     var $paddable = false;\r
422 \r
423     /**\r
424      * Encryption buffer for CTR, OFB and CFB modes\r
425      *\r
426      * @see Crypt_Rijndael::encrypt()\r
427      * @var String\r
428      * @access private\r
429      */\r
430     var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0);\r
431 \r
432     /**\r
433      * Decryption buffer for CTR, OFB and CFB modes\r
434      *\r
435      * @see Crypt_Rijndael::decrypt()\r
436      * @var String\r
437      * @access private\r
438      */\r
439     var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0);\r
440 \r
441     /**\r
442      * Default Constructor.\r
443      *\r
444      * Determines whether or not the mcrypt extension should be used.  $mode should only, at present, be\r
445      * CRYPT_RIJNDAEL_MODE_ECB or CRYPT_RIJNDAEL_MODE_CBC.  If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.\r
446      *\r
447      * @param optional Integer $mode\r
448      * @return Crypt_Rijndael\r
449      * @access public\r
450      */\r
451     function Crypt_Rijndael($mode = CRYPT_RIJNDAEL_MODE_CBC)\r
452     {\r
453         switch ($mode) {\r
454             case CRYPT_RIJNDAEL_MODE_ECB:\r
455             case CRYPT_RIJNDAEL_MODE_CBC:\r
456                 $this->paddable = true;\r
457                 $this->mode = $mode;\r
458                 break;\r
459             case CRYPT_RIJNDAEL_MODE_CTR:\r
460             case CRYPT_RIJNDAEL_MODE_CFB:\r
461             case CRYPT_RIJNDAEL_MODE_OFB:\r
462                 $this->mode = $mode;\r
463                 break;\r
464             default:\r
465                 $this->paddable = true;\r
466                 $this->mode = CRYPT_RIJNDAEL_MODE_CBC;\r
467         }\r
468 \r
469         $t3 = &$this->t3;\r
470         $t2 = &$this->t2;\r
471         $t1 = &$this->t1;\r
472         $t0 = &$this->t0;\r
473 \r
474         $dt3 = &$this->dt3;\r
475         $dt2 = &$this->dt2;\r
476         $dt1 = &$this->dt1;\r
477         $dt0 = &$this->dt0;\r
478 \r
479         // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1), \r
480         // precomputed tables can be used in the mixColumns phase.  in that example, they're assigned t0...t3, so\r
481         // those are the names we'll use.\r
482         $t3 = array(\r
483             0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, \r
484             0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, \r
485             0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, \r
486             0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, \r
487             0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, \r
488             0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, \r
489             0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, \r
490             0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, \r
491             0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, \r
492             0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, \r
493             0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, \r
494             0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, \r
495             0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, \r
496             0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, \r
497             0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, \r
498             0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, \r
499             0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, \r
500             0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, \r
501             0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, \r
502             0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, \r
503             0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, \r
504             0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, \r
505             0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, \r
506             0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, \r
507             0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, \r
508             0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, \r
509             0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, \r
510             0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, \r
511             0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, \r
512             0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, \r
513             0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, \r
514             0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C\r
515         );\r
516 \r
517         $dt3 = array(\r
518             0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, \r
519             0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, \r
520             0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, \r
521             0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, \r
522             0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, \r
523             0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, \r
524             0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, \r
525             0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, \r
526             0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, \r
527             0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, \r
528             0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, \r
529             0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, \r
530             0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, \r
531             0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, \r
532             0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, \r
533             0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, \r
534             0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, \r
535             0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, \r
536             0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, \r
537             0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, \r
538             0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, \r
539             0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, \r
540             0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, \r
541             0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, \r
542             0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, \r
543             0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, \r
544             0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, \r
545             0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, \r
546             0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, \r
547             0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, \r
548             0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, \r
549             0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0\r
550         );\r
551 \r
552         for ($i = 0; $i < 256; $i++) {\r
553             $t2[] = (($t3[$i] <<  8) & 0xFFFFFF00) | (($t3[$i] >> 24) & 0x000000FF);\r
554             $t1[] = (($t3[$i] << 16) & 0xFFFF0000) | (($t3[$i] >> 16) & 0x0000FFFF);\r
555             $t0[] = (($t3[$i] << 24) & 0xFF000000) | (($t3[$i] >>  8) & 0x00FFFFFF);\r
556 \r
557             $dt2[] = (($dt3[$i] <<  8) & 0xFFFFFF00) | (($dt3[$i] >> 24) & 0x000000FF);\r
558             $dt1[] = (($dt3[$i] << 16) & 0xFFFF0000) | (($dt3[$i] >> 16) & 0x0000FFFF);\r
559             $dt0[] = (($dt3[$i] << 24) & 0xFF000000) | (($dt3[$i] >>  8) & 0x00FFFFFF);\r
560         }\r
561 \r
562         // sbox for the S-Box substitution\r
563         $this->sbox = array(\r
564             0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,\r
565             0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,\r
566             0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,\r
567             0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,\r
568             0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,\r
569             0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,\r
570             0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,\r
571             0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,\r
572             0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,\r
573             0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,\r
574             0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,\r
575             0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,\r
576             0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,\r
577             0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,\r
578             0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,\r
579             0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16\r
580         );\r
581 \r
582         // sbox for the inverse S-Box substitution\r
583         $this->isbox = array(\r
584             0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,\r
585             0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,\r
586             0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,\r
587             0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,\r
588             0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,\r
589             0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,\r
590             0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,\r
591             0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,\r
592             0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,\r
593             0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,\r
594             0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,\r
595             0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,\r
596             0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,\r
597             0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,\r
598             0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,\r
599             0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D\r
600         );\r
601 \r
602         if (!function_exists('create_function') || !is_callable('create_function')) {\r
603             $this->use_inline_crypt = false;\r
604         }\r
605     }\r
606 \r
607     /**\r
608      * Sets the key.\r
609      *\r
610      * Keys can be of any length.  Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and\r
611      * whose length is a multiple of 32.  If the key is less than 256-bits and the key length isn't set, we round the length\r
612      * up to the closest valid key length, padding $key with null bytes.  If the key is more than 256-bits, we trim the\r
613      * excess bits.\r
614      *\r
615      * If the key is not explicitly set, it'll be assumed to be all null bytes.\r
616      *\r
617      * @access public\r
618      * @param String $key\r
619      */\r
620     function setKey($key)\r
621     {\r
622         $this->key = $key;\r
623         $this->changed = true;\r
624     }\r
625 \r
626     /**\r
627      * Sets the initialization vector. (optional)\r
628      *\r
629      * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used.  If not explictly set, it'll be assumed\r
630      * to be all zero's.\r
631      *\r
632      * @access public\r
633      * @param String $iv\r
634      */\r
635     function setIV($iv)\r
636     {\r
637         $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, $this->block_size), $this->block_size, chr(0));\r
638     }\r
639 \r
640     /**\r
641      * Sets the key length\r
642      *\r
643      * Valid key lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to\r
644      * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.\r
645      *\r
646      * @access public\r
647      * @param Integer $length\r
648      */\r
649     function setKeyLength($length)\r
650     {\r
651         $length >>= 5;\r
652         if ($length > 8) {\r
653             $length = 8;\r
654         } else if ($length < 4) {\r
655             $length = 4;\r
656         }\r
657         $this->Nk = $length;\r
658         $this->key_size = $length << 2;\r
659 \r
660         $this->explicit_key_length = true;\r
661         $this->changed = true;\r
662     }\r
663 \r
664     /**\r
665      * Sets the password.\r
666      *\r
667      * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:\r
668      *     {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:\r
669      *         $hash, $salt, $method\r
670      *     Set $dkLen by calling setKeyLength()\r
671      *\r
672      * @param String $password\r
673      * @param optional String $method\r
674      * @access public\r
675      */\r
676     function setPassword($password, $method = 'pbkdf2')\r
677     {\r
678         $key = '';\r
679 \r
680         switch ($method) {\r
681             default: // 'pbkdf2'\r
682                 list(, , $hash, $salt, $count) = func_get_args();\r
683                 if (!isset($hash)) {\r
684                     $hash = 'sha1';\r
685                 }\r
686                 // WPA and WPA2 use the SSID as the salt\r
687                 if (!isset($salt)) {\r
688                     $salt = 'phpseclib';\r
689                 }\r
690                 // RFC2898#section-4.2 uses 1,000 iterations by default\r
691                 // WPA and WPA2 use 4,096.\r
692                 if (!isset($count)) {\r
693                     $count = 1000;\r
694                 }\r
695 \r
696                 if (!class_exists('Crypt_Hash')) {\r
697                     require_once('Crypt/Hash.php');\r
698                 }\r
699 \r
700                 $i = 1;\r
701                 while (strlen($key) < $this->key_size) { // $dkLen == $this->key_size\r
702                     //$dk.= $this->_pbkdf($password, $salt, $count, $i++);\r
703                     $hmac = new Crypt_Hash();\r
704                     $hmac->setHash($hash);\r
705                     $hmac->setKey($password);\r
706                     $f = $u = $hmac->hash($salt . pack('N', $i++));\r
707                     for ($j = 2; $j <= $count; $j++) {\r
708                         $u = $hmac->hash($u);\r
709                         $f^= $u;\r
710                     }\r
711                     $key.= $f;\r
712                 }\r
713         }\r
714 \r
715         $this->setKey(substr($key, 0, $this->key_size));\r
716     }\r
717 \r
718     /**\r
719      * Sets the block length\r
720      *\r
721      * Valid block lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to\r
722      * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.\r
723      *\r
724      * @access public\r
725      * @param Integer $length\r
726      */\r
727     function setBlockLength($length)\r
728     {\r
729         $length >>= 5;\r
730         if ($length > 8) {\r
731             $length = 8;\r
732         } else if ($length < 4) {\r
733             $length = 4;\r
734         }\r
735         $this->Nb = $length;\r
736         $this->block_size = $length << 2;\r
737         $this->changed = true;\r
738     }\r
739 \r
740     /**\r
741      * Generate CTR XOR encryption key\r
742      *\r
743      * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the\r
744      * plaintext / ciphertext in CTR mode.\r
745      *\r
746      * @see Crypt_Rijndael::decrypt()\r
747      * @see Crypt_Rijndael::encrypt()\r
748      * @access public\r
749      * @param Integer $length\r
750      * @param String $iv\r
751      */\r
752     function _generate_xor($length, &$iv)\r
753     {\r
754         $xor = '';\r
755         $block_size = $this->block_size;\r
756         $num_blocks = floor(($length + ($block_size - 1)) / $block_size);\r
757         for ($i = 0; $i < $num_blocks; $i++) {\r
758             $xor.= $iv;\r
759             for ($j = 4; $j <= $block_size; $j+=4) {\r
760                 $temp = substr($iv, -$j, 4);\r
761                 switch ($temp) {\r
762                     case "\xFF\xFF\xFF\xFF":\r
763                         $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);\r
764                         break;\r
765                     case "\x7F\xFF\xFF\xFF":\r
766                         $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);\r
767                         break 2;\r
768                     default:\r
769                         extract(unpack('Ncount', $temp));\r
770                         $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);\r
771                         break 2;\r
772                 }\r
773             }\r
774         }\r
775 \r
776         return $xor;\r
777     }\r
778 \r
779     /**\r
780      * Encrypts a message.\r
781      *\r
782      * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size.  Other Rjindael\r
783      * implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's\r
784      * necessary are discussed in the following\r
785      * URL:\r
786      *\r
787      * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}\r
788      *\r
789      * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.\r
790      * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that\r
791      * length.\r
792      *\r
793      * @see Crypt_Rijndael::decrypt()\r
794      * @access public\r
795      * @param String $plaintext\r
796      */\r
797     function encrypt($plaintext)\r
798     {\r
799         if ($this->changed) {\r
800             $this->_setup();\r
801         }\r
802         if ($this->use_inline_crypt) {\r
803             $inline = $this->inline_crypt;\r
804             return $inline('encrypt', $this, $plaintext);\r
805         }\r
806         if ($this->paddable) {\r
807             $plaintext = $this->_pad($plaintext);\r
808         }\r
809 \r
810         $block_size = $this->block_size;\r
811         $buffer = &$this->enbuffer;\r
812         $ciphertext = '';\r
813         switch ($this->mode) {\r
814             case CRYPT_RIJNDAEL_MODE_ECB:\r
815                 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {\r
816                     $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));\r
817                 }\r
818                 break;\r
819             case CRYPT_RIJNDAEL_MODE_CBC:\r
820                 $xor = $this->encryptIV;\r
821                 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {\r
822                     $block = substr($plaintext, $i, $block_size);\r
823                     $block = $this->_encryptBlock($block ^ $xor);\r
824                     $xor = $block;\r
825                     $ciphertext.= $block;\r
826                 }\r
827                 if ($this->continuousBuffer) {\r
828                     $this->encryptIV = $xor;\r
829                 }\r
830                 break;\r
831             case CRYPT_RIJNDAEL_MODE_CTR:\r
832                 $xor = $this->encryptIV;\r
833                 if (strlen($buffer['encrypted'])) {\r
834                     for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {\r
835                         $block = substr($plaintext, $i, $block_size);\r
836                         if (strlen($block) > strlen($buffer['encrypted'])) {\r
837                             $buffer['encrypted'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));\r
838                         }\r
839                         $key = $this->_string_shift($buffer['encrypted'], $block_size);\r
840                         $ciphertext.= $block ^ $key;\r
841                     }\r
842                 } else {\r
843                     for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {\r
844                         $block = substr($plaintext, $i, $block_size);\r
845                         $key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));\r
846                         $ciphertext.= $block ^ $key;\r
847                     }\r
848                 }\r
849                 if ($this->continuousBuffer) {\r
850                     $this->encryptIV = $xor;\r
851                     if ($start = strlen($plaintext) % $block_size) {\r
852                         $buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];\r
853                     }\r
854                 }\r
855                 break;\r
856             case CRYPT_RIJNDAEL_MODE_CFB:\r
857                 // cfb loosely routines inspired by openssl's:\r
858                 // http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1\r
859                 if ($this->continuousBuffer) {\r
860                     $iv = &$this->encryptIV;\r
861                     $pos = &$buffer['pos'];\r
862                 } else {\r
863                     $iv = $this->encryptIV;\r
864                     $pos = 0;\r
865                 }\r
866                 $len = strlen($plaintext);\r
867                 $i = 0;\r
868                 if ($pos) {\r
869                     $orig_pos = $pos;\r
870                     $max = $block_size - $pos;\r
871                     if ($len >= $max) {\r
872                         $i = $max;\r
873                         $len-= $max;\r
874                         $pos = 0;\r
875                     } else {\r
876                         $i = $len;\r
877                         $pos+= $len;\r
878                         $len = 0;\r
879                     }\r
880                     // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize\r
881                     $ciphertext = substr($iv, $orig_pos) ^ $plaintext;\r
882                     $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);\r
883                 }\r
884                 while ($len >= $block_size) {\r
885                     $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);\r
886                     $ciphertext.= $iv;\r
887                     $len-= $block_size;\r
888                     $i+= $block_size;\r
889                 }\r
890                 if ($len) {\r
891                     $iv = $this->_encryptBlock($iv);\r
892                     $block = $iv ^ substr($plaintext, $i);\r
893                     $iv = substr_replace($iv, $block, 0, $len);\r
894                     $ciphertext.= $block;\r
895                     $pos = $len;\r
896                 }\r
897                 break;\r
898             case CRYPT_RIJNDAEL_MODE_OFB:\r
899                 $xor = $this->encryptIV;\r
900                 if (strlen($buffer['xor'])) {\r
901                     for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {\r
902                         $block = substr($plaintext, $i, $block_size);\r
903                         if (strlen($block) > strlen($buffer['xor'])) {\r
904                             $xor = $this->_encryptBlock($xor);\r
905                             $buffer['xor'].= $xor;\r
906                         }\r
907                         $key = $this->_string_shift($buffer['xor'], $block_size);\r
908                         $ciphertext.= $block ^ $key;\r
909                     }\r
910                 } else {\r
911                     for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {\r
912                         $xor = $this->_encryptBlock($xor);\r
913                         $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;\r
914                     }\r
915                     $key = $xor;\r
916                 }\r
917                 if ($this->continuousBuffer) {\r
918                     $this->encryptIV = $xor;\r
919                     if ($start = strlen($plaintext) % $block_size) {\r
920                          $buffer['xor'] = substr($key, $start) . $buffer['xor'];\r
921                     }\r
922                 }\r
923         }\r
924 \r
925         return $ciphertext;\r
926     }\r
927 \r
928     /**\r
929      * Decrypts a message.\r
930      *\r
931      * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until\r
932      * it is.\r
933      *\r
934      * @see Crypt_Rijndael::encrypt()\r
935      * @access public\r
936      * @param String $ciphertext\r
937      */\r
938     function decrypt($ciphertext)\r
939     {\r
940         if ($this->changed) {\r
941             $this->_setup();\r
942         }\r
943         if ($this->use_inline_crypt) {\r
944             $inline = $this->inline_crypt;\r
945             return $inline('decrypt', $this, $ciphertext);\r
946         }\r
947         if ($this->paddable) {\r
948             // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :\r
949             // "The data is padded with "\0" to make sure the length of the data is n * blocksize."\r
950             $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));\r
951         }\r
952 \r
953         $block_size = $this->block_size;\r
954         $buffer = &$this->debuffer;\r
955         $plaintext = '';\r
956         switch ($this->mode) {\r
957             case CRYPT_RIJNDAEL_MODE_ECB:\r
958                 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {\r
959                     $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));\r
960                 }\r
961                 break;\r
962             case CRYPT_RIJNDAEL_MODE_CBC:\r
963                 $xor = $this->decryptIV;\r
964                 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {\r
965                     $block = substr($ciphertext, $i, $block_size);\r
966                     $plaintext.= $this->_decryptBlock($block) ^ $xor;\r
967                     $xor = $block;\r
968                 }\r
969                 if ($this->continuousBuffer) {\r
970                     $this->decryptIV = $xor;\r
971                 }\r
972                 break;\r
973             case CRYPT_RIJNDAEL_MODE_CTR:\r
974                 $xor = $this->decryptIV;\r
975                 if (strlen($buffer['ciphertext'])) {\r
976                     for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {\r
977                         $block = substr($ciphertext, $i, $block_size);\r
978                         if (strlen($block) > strlen($buffer['ciphertext'])) {\r
979                             $buffer['ciphertext'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));\r
980                         }\r
981                         $key = $this->_string_shift($buffer['ciphertext'], $block_size);\r
982                         $plaintext.= $block ^ $key;\r
983                     }\r
984                 } else {\r
985                     for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {\r
986                         $block = substr($ciphertext, $i, $block_size);\r
987                         $key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));\r
988                         $plaintext.= $block ^ $key;\r
989                     }\r
990                 }\r
991                 if ($this->continuousBuffer) {\r
992                     $this->decryptIV = $xor;\r
993                     if ($start = strlen($ciphertext) % $block_size) {\r
994                         $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];\r
995                     }\r
996                 }\r
997                 break;\r
998             case CRYPT_RIJNDAEL_MODE_CFB:\r
999                 if ($this->continuousBuffer) {\r
1000                     $iv = &$this->decryptIV;\r
1001                     $pos = &$buffer['pos'];\r
1002                 } else {\r
1003                     $iv = $this->decryptIV;\r
1004                     $pos = 0;\r
1005                 }\r
1006                 $len = strlen($ciphertext);\r
1007                 $i = 0;\r
1008                 if ($pos) {\r
1009                     $orig_pos = $pos;\r
1010                     $max = $block_size - $pos;\r
1011                     if ($len >= $max) {\r
1012                         $i = $max;\r
1013                         $len-= $max;\r
1014                         $pos = 0;\r
1015                     } else {\r
1016                         $i = $len;\r
1017                         $pos+= $len;\r
1018                         $len = 0;\r
1019                     }\r
1020                     // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize\r
1021                     $plaintext = substr($iv, $orig_pos) ^ $ciphertext;\r
1022                     $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);\r
1023                 }\r
1024                 while ($len >= $block_size) {\r
1025                     $iv = $this->_encryptBlock($iv);\r
1026                     $cb = substr($ciphertext, $i, $block_size);\r
1027                     $plaintext.= $iv ^ $cb;\r
1028                     $iv = $cb;\r
1029                     $len-= $block_size;\r
1030                     $i+= $block_size;\r
1031                 }\r
1032                 if ($len) {\r
1033                     $iv = $this->_encryptBlock($iv);\r
1034                     $plaintext.= $iv ^ substr($ciphertext, $i);\r
1035                     $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);\r
1036                     $pos = $len;\r
1037                 }\r
1038                 break;\r
1039             case CRYPT_RIJNDAEL_MODE_OFB:\r
1040                 $xor = $this->decryptIV;\r
1041                 if (strlen($buffer['xor'])) {\r
1042                     for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {\r
1043                         $block = substr($ciphertext, $i, $block_size);\r
1044                         if (strlen($block) > strlen($buffer['xor'])) {\r
1045                             $xor = $this->_encryptBlock($xor);\r
1046                             $buffer['xor'].= $xor;\r
1047                         }\r
1048                         $key = $this->_string_shift($buffer['xor'], $block_size);\r
1049                         $plaintext.= $block ^ $key;\r
1050                     }\r
1051                 } else {\r
1052                     for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {\r
1053                         $xor = $this->_encryptBlock($xor);\r
1054                         $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;\r
1055                     }\r
1056                     $key = $xor;\r
1057                 }\r
1058                 if ($this->continuousBuffer) {\r
1059                     $this->decryptIV = $xor;\r
1060                     if ($start = strlen($ciphertext) % $block_size) {\r
1061                          $buffer['xor'] = substr($key, $start) . $buffer['xor'];\r
1062                     }\r
1063                 }\r
1064         }\r
1065 \r
1066         return $this->paddable ? $this->_unpad($plaintext) : $plaintext;\r
1067     }\r
1068 \r
1069     /**\r
1070      * Encrypts a block\r
1071      *\r
1072      * @access private\r
1073      * @param String $in\r
1074      * @return String\r
1075      */\r
1076     function _encryptBlock($in)\r
1077     {\r
1078         $state = array();\r
1079         $words = unpack('N*word', $in);\r
1080 \r
1081         $w = $this->w;\r
1082         $t0 = $this->t0;\r
1083         $t1 = $this->t1;\r
1084         $t2 = $this->t2;\r
1085         $t3 = $this->t3;\r
1086         $Nb = $this->Nb;\r
1087         $Nr = $this->Nr;\r
1088         $c = $this->c;\r
1089 \r
1090         // addRoundKey\r
1091         $i = -1;\r
1092         foreach ($words as $word) {\r
1093             $state[] = $word ^ $w[0][++$i];\r
1094         }\r
1095 \r
1096         // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components - \r
1097         // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding \r
1098         // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.\r
1099         // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.\r
1100         // Unfortunately, the description given there is not quite correct.  Per aes.spec.v316.pdf#page=19 [1], \r
1101         // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.\r
1102 \r
1103         // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf\r
1104         $temp = array();\r
1105         for ($round = 1; $round < $Nr; ++$round) {\r
1106             $i = 0; // $c[0] == 0\r
1107             $j = $c[1];\r
1108             $k = $c[2];\r
1109             $l = $c[3];\r
1110 \r
1111             while ($i < $Nb) {\r
1112                 $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^\r
1113                             $t1[$state[$j] >> 16 & 0x000000FF] ^\r
1114                             $t2[$state[$k] >>  8 & 0x000000FF] ^\r
1115                             $t3[$state[$l]       & 0x000000FF] ^\r
1116                             $w[$round][$i];\r
1117                 ++$i;\r
1118                 $j = ($j + 1) % $Nb;\r
1119                 $k = ($k + 1) % $Nb;\r
1120                 $l = ($l + 1) % $Nb;\r
1121             }\r
1122             $state = $temp;\r
1123         }\r
1124 \r
1125         // subWord\r
1126         for ($i = 0; $i < $Nb; ++$i) {\r
1127             $state[$i] = $this->_subWord($state[$i]);\r
1128         }\r
1129 \r
1130         // shiftRows + addRoundKey\r
1131         $i = 0; // $c[0] == 0\r
1132         $j = $c[1];\r
1133         $k = $c[2];\r
1134         $l = $c[3];\r
1135         while ($i < $Nb) {\r
1136             $temp[$i] = ($state[$i] & 0xFF000000) ^\r
1137                         ($state[$j] & 0x00FF0000) ^\r
1138                         ($state[$k] & 0x0000FF00) ^\r
1139                         ($state[$l] & 0x000000FF) ^\r
1140                          $w[$Nr][$i];\r
1141             ++$i;\r
1142             $j = ($j + 1) % $Nb;\r
1143             $k = ($k + 1) % $Nb;\r
1144             $l = ($l + 1) % $Nb;\r
1145         }\r
1146 \r
1147         // 100% ugly switch/case code... but ~5% faster ("smart code" below commented out)\r
1148         switch ($Nb) {\r
1149             case 8:\r
1150                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);\r
1151             case 7:\r
1152                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);\r
1153             case 6:\r
1154                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);\r
1155             case 5:\r
1156                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);\r
1157             default:\r
1158                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);\r
1159         }\r
1160         /*\r
1161         $state = $temp;\r
1162 \r
1163         array_unshift($state, 'N*');\r
1164 \r
1165         return call_user_func_array('pack', $state);\r
1166         */\r
1167     }\r
1168 \r
1169     /**\r
1170      * Decrypts a block\r
1171      *\r
1172      * @access private\r
1173      * @param String $in\r
1174      * @return String\r
1175      */\r
1176     function _decryptBlock($in)\r
1177     {\r
1178         $state = array();\r
1179         $words = unpack('N*word', $in);\r
1180 \r
1181         $dw = $this->dw;\r
1182         $dt0 = $this->dt0;\r
1183         $dt1 = $this->dt1;\r
1184         $dt2 = $this->dt2;\r
1185         $dt3 = $this->dt3;\r
1186         $Nb = $this->Nb;\r
1187         $Nr = $this->Nr;\r
1188         $c = $this->c;\r
1189 \r
1190         // addRoundKey\r
1191         $i = -1;\r
1192         foreach ($words as $word) {\r
1193             $state[] = $word ^ $dw[$Nr][++$i];\r
1194         }\r
1195 \r
1196         $temp = array();\r
1197         for ($round = $Nr - 1; $round > 0; --$round) {\r
1198             $i = 0; // $c[0] == 0\r
1199             $j = $Nb - $c[1];\r
1200             $k = $Nb - $c[2];\r
1201             $l = $Nb - $c[3];\r
1202 \r
1203             while ($i < $Nb) {\r
1204                 $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^\r
1205                             $dt1[$state[$j] >> 16 & 0x000000FF] ^\r
1206                             $dt2[$state[$k] >>  8 & 0x000000FF] ^\r
1207                             $dt3[$state[$l]       & 0x000000FF] ^\r
1208                             $dw[$round][$i];\r
1209                 ++$i;\r
1210                 $j = ($j + 1) % $Nb;\r
1211                 $k = ($k + 1) % $Nb;\r
1212                 $l = ($l + 1) % $Nb;\r
1213             }\r
1214             $state = $temp;\r
1215         }\r
1216 \r
1217         // invShiftRows + invSubWord + addRoundKey\r
1218         $i = 0; // $c[0] == 0\r
1219         $j = $Nb - $c[1];\r
1220         $k = $Nb - $c[2];\r
1221         $l = $Nb - $c[3];\r
1222 \r
1223         while ($i < $Nb) {\r
1224             $temp[$i] = $dw[0][$i] ^ \r
1225                         $this->_invSubWord(($state[$i] & 0xFF000000) | \r
1226                                            ($state[$j] & 0x00FF0000) | \r
1227                                            ($state[$k] & 0x0000FF00) | \r
1228                                            ($state[$l] & 0x000000FF));\r
1229             ++$i;\r
1230             $j = ($j + 1) % $Nb;\r
1231             $k = ($k + 1) % $Nb;\r
1232             $l = ($l + 1) % $Nb;\r
1233         }\r
1234 \r
1235         switch ($Nb) {\r
1236             case 8:\r
1237                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);\r
1238             case 7:\r
1239                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);\r
1240             case 6:\r
1241                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);\r
1242             case 5:\r
1243                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);\r
1244             default:\r
1245                 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);\r
1246         }\r
1247         /*\r
1248         $state = $temp;\r
1249 \r
1250         array_unshift($state, 'N*');\r
1251 \r
1252         return call_user_func_array('pack', $state);\r
1253         */\r
1254     }\r
1255 \r
1256     /**\r
1257      * Setup Rijndael\r
1258      *\r
1259      * Validates all the variables and calculates $Nr - the number of rounds that need to be performed - and $w - the key\r
1260      * key schedule.\r
1261      *\r
1262      * @access private\r
1263      */\r
1264     function _setup()\r
1265     {\r
1266         // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.\r
1267         // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse\r
1268         static $rcon = array(0,\r
1269             0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,\r
1270             0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,\r
1271             0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,\r
1272             0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,\r
1273             0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,\r
1274             0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000\r
1275         );\r
1276 \r
1277         if (!$this->explicit_key_length) {\r
1278             // we do >> 2, here, and not >> 5, as we do above, since strlen($this->key) tells us the number of bytes - not bits\r
1279             $length = strlen($this->key) >> 2;\r
1280             if ($length > 8) {\r
1281                 $length = 8;\r
1282             } else if ($length < 4) {\r
1283                 $length = 4;\r
1284             }\r
1285             $this->Nk = $length;\r
1286             $this->key_size = $length << 2;\r
1287         }\r
1288 \r
1289         $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));\r
1290         $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, chr(0));\r
1291 \r
1292         // see Rijndael-ammended.pdf#page=44\r
1293         $this->Nr = max($this->Nk, $this->Nb) + 6;\r
1294 \r
1295         // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,\r
1296         //     "Table 8: Shift offsets in Shiftrow for the alternative block lengths"\r
1297         // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,\r
1298         //     "Table 2: Shift offsets for different block lengths"\r
1299         switch ($this->Nb) {\r
1300             case 4:\r
1301             case 5:\r
1302             case 6:\r
1303                 $this->c = array(0, 1, 2, 3);\r
1304                 break;\r
1305             case 7:\r
1306                 $this->c = array(0, 1, 2, 4);\r
1307                 break;\r
1308             case 8:\r
1309                 $this->c = array(0, 1, 3, 4);\r
1310         }\r
1311 \r
1312         $key = $this->key;\r
1313 \r
1314         $w = array_values(unpack('N*words', $key));\r
1315 \r
1316         $length = $this->Nb * ($this->Nr + 1);\r
1317         for ($i = $this->Nk; $i < $length; $i++) {\r
1318             $temp = $w[$i - 1];\r
1319             if ($i % $this->Nk == 0) {\r
1320                 // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".\r
1321                 // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,\r
1322                 // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'\r
1323                 // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.\r
1324                 $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord\r
1325                 $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];\r
1326             } else if ($this->Nk > 6 && $i % $this->Nk == 4) {\r
1327                 $temp = $this->_subWord($temp);\r
1328             }\r
1329             $w[$i] = $w[$i - $this->Nk] ^ $temp;\r
1330         }\r
1331 \r
1332         // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns\r
1333         // and generate the inverse key schedule.  more specifically,\r
1334         // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3), \r
1335         // "The key expansion for the Inverse Cipher is defined as follows:\r
1336         //        1. Apply the Key Expansion.\r
1337         //        2. Apply InvMixColumn to all Round Keys except the first and the last one."\r
1338         // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"\r
1339         $temp = $this->w = $this->dw = array();\r
1340         for ($i = $row = $col = 0; $i < $length; $i++, $col++) {\r
1341             if ($col == $this->Nb) {\r
1342                 if ($row == 0) {\r
1343                     $this->dw[0] = $this->w[0];\r
1344                 } else {\r
1345                     // subWord + invMixColumn + invSubWord = invMixColumn\r
1346                     $j = 0;\r
1347                     while ($j < $this->Nb) {\r
1348                         $dw = $this->_subWord($this->w[$row][$j]);\r
1349                         $temp[$j] = $this->dt0[$dw >> 24 & 0x000000FF] ^ \r
1350                                     $this->dt1[$dw >> 16 & 0x000000FF] ^ \r
1351                                     $this->dt2[$dw >>  8 & 0x000000FF] ^ \r
1352                                     $this->dt3[$dw       & 0x000000FF];\r
1353                         $j++;\r
1354                     }\r
1355                     $this->dw[$row] = $temp;\r
1356                 }\r
1357 \r
1358                 $col = 0;\r
1359                 $row++;\r
1360             }\r
1361             $this->w[$row][$col] = $w[$i];\r
1362         }\r
1363 \r
1364         $this->dw[$row] = $this->w[$row];\r
1365 \r
1366         // In case of $this->use_inline_crypt === true we have to use 1-dim key arrays (both ascending)\r
1367         if ($this->use_inline_crypt) {\r
1368             $this->dw = array_reverse($this->dw);\r
1369             $w  = array_pop($this->w);\r
1370             $dw = array_pop($this->dw);\r
1371             foreach ($this->w as $r => $wr) {\r
1372                 foreach ($wr as $c => $wc) {\r
1373                     $w[]  = $wc;\r
1374                     $dw[] = $this->dw[$r][$c];\r
1375                 }\r
1376             }\r
1377             $this->w  = $w;\r
1378             $this->dw = $dw;\r
1379 \r
1380             $this->inline_crypt_setup();\r
1381         }\r
1382 \r
1383         $this->changed = false;\r
1384     }\r
1385 \r
1386     /**\r
1387      * Performs S-Box substitutions\r
1388      *\r
1389      * @access private\r
1390      */\r
1391     function _subWord($word)\r
1392     {\r
1393         $sbox = $this->sbox;\r
1394 \r
1395         return  $sbox[$word       & 0x000000FF]        |\r
1396                ($sbox[$word >>  8 & 0x000000FF] <<  8) |\r
1397                ($sbox[$word >> 16 & 0x000000FF] << 16) |\r
1398                ($sbox[$word >> 24 & 0x000000FF] << 24);\r
1399     }\r
1400 \r
1401     /**\r
1402      * Performs inverse S-Box substitutions\r
1403      *\r
1404      * @access private\r
1405      */\r
1406     function _invSubWord($word)\r
1407     {\r
1408         $isbox = $this->isbox;\r
1409 \r
1410         return  $isbox[$word       & 0x000000FF]        |\r
1411                ($isbox[$word >>  8 & 0x000000FF] <<  8) |\r
1412                ($isbox[$word >> 16 & 0x000000FF] << 16) |\r
1413                ($isbox[$word >> 24 & 0x000000FF] << 24);\r
1414     }\r
1415 \r
1416     /**\r
1417      * Pad "packets".\r
1418      *\r
1419      * Rijndael works by encrypting between sixteen and thirty-two bytes at a time, provided that number is also a multiple\r
1420      * of four.  If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to\r
1421      * pad the input so that it is of the proper length.\r
1422      *\r
1423      * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH,\r
1424      * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping\r
1425      * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is\r
1426      * transmitted separately)\r
1427      *\r
1428      * @see Crypt_Rijndael::disablePadding()\r
1429      * @access public\r
1430      */\r
1431     function enablePadding()\r
1432     {\r
1433         $this->padding = true;\r
1434     }\r
1435 \r
1436     /**\r
1437      * Do not pad packets.\r
1438      *\r
1439      * @see Crypt_Rijndael::enablePadding()\r
1440      * @access public\r
1441      */\r
1442     function disablePadding()\r
1443     {\r
1444         $this->padding = false;\r
1445     }\r
1446 \r
1447     /**\r
1448      * Pads a string\r
1449      *\r
1450      * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.\r
1451      * $block_size - (strlen($text) % $block_size) bytes are added, each of which is equal to \r
1452      * chr($block_size - (strlen($text) % $block_size)\r
1453      *\r
1454      * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless\r
1455      * and padding will, hence forth, be enabled.\r
1456      *\r
1457      * @see Crypt_Rijndael::_unpad()\r
1458      * @access private\r
1459      */\r
1460     function _pad($text)\r
1461     {\r
1462         $length = strlen($text);\r
1463 \r
1464         if (!$this->padding) {\r
1465             if ($length % $this->block_size == 0) {\r
1466                 return $text;\r
1467             } else {\r
1468                 user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");\r
1469                 $this->padding = true;\r
1470             }\r
1471         }\r
1472 \r
1473         $pad = $this->block_size - ($length % $this->block_size);\r
1474 \r
1475         return str_pad($text, $length + $pad, chr($pad));\r
1476     }\r
1477 \r
1478     /**\r
1479      * Unpads a string.\r
1480      *\r
1481      * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong\r
1482      * and false will be returned.\r
1483      *\r
1484      * @see Crypt_Rijndael::_pad()\r
1485      * @access private\r
1486      */\r
1487     function _unpad($text)\r
1488     {\r
1489         if (!$this->padding) {\r
1490             return $text;\r
1491         }\r
1492 \r
1493         $length = ord($text[strlen($text) - 1]);\r
1494 \r
1495         if (!$length || $length > $this->block_size) {\r
1496             return false;\r
1497         }\r
1498 \r
1499         return substr($text, 0, -$length);\r
1500     }\r
1501 \r
1502     /**\r
1503      * Treat consecutive "packets" as if they are a continuous buffer.\r
1504      *\r
1505      * Say you have a 32-byte plaintext $plaintext.  Using the default behavior, the two following code snippets\r
1506      * will yield different outputs:\r
1507      *\r
1508      * <code>\r
1509      *    echo $rijndael->encrypt(substr($plaintext,  0, 16));\r
1510      *    echo $rijndael->encrypt(substr($plaintext, 16, 16));\r
1511      * </code>\r
1512      * <code>\r
1513      *    echo $rijndael->encrypt($plaintext);\r
1514      * </code>\r
1515      *\r
1516      * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates\r
1517      * another, as demonstrated with the following:\r
1518      *\r
1519      * <code>\r
1520      *    $rijndael->encrypt(substr($plaintext, 0, 16));\r
1521      *    echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));\r
1522      * </code>\r
1523      * <code>\r
1524      *    echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));\r
1525      * </code>\r
1526      *\r
1527      * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different\r
1528      * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /\r
1529      * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.\r
1530      *\r
1531      * Put another way, when the continuous buffer is enabled, the state of the Crypt_Rijndael() object changes after each\r
1532      * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that\r
1533      * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),\r
1534      * however, they are also less intuitive and more likely to cause you problems.\r
1535      *\r
1536      * @see Crypt_Rijndael::disableContinuousBuffer()\r
1537      * @access public\r
1538      */\r
1539     function enableContinuousBuffer()\r
1540     {\r
1541         $this->continuousBuffer = true;\r
1542     }\r
1543 \r
1544     /**\r
1545      * Treat consecutive packets as if they are a discontinuous buffer.\r
1546      *\r
1547      * The default behavior.\r
1548      *\r
1549      * @see Crypt_Rijndael::enableContinuousBuffer()\r
1550      * @access public\r
1551      */\r
1552     function disableContinuousBuffer()\r
1553     {\r
1554         $this->continuousBuffer = false;\r
1555         $this->encryptIV = $this->iv;\r
1556         $this->decryptIV = $this->iv;\r
1557         $this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0);\r
1558         $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0);\r
1559     }\r
1560 \r
1561     /**\r
1562      * String Shift\r
1563      *\r
1564      * Inspired by array_shift\r
1565      *\r
1566      * @param String $string\r
1567      * @param optional Integer $index\r
1568      * @return String\r
1569      * @access private\r
1570      */\r
1571     function _string_shift(&$string, $index = 1)\r
1572     {\r
1573         $substr = substr($string, 0, $index);\r
1574         $string = substr($string, $index);\r
1575         return $substr;\r
1576     }\r
1577 \r
1578     /**\r
1579      * Creates performance-optimized function for de/encrypt(), storing it in $this->inline_crypt\r
1580      *\r
1581      * @see Crypt_Rijndael::encrypt()\r
1582      * @see Crypt_Rijndael::decrypt()\r
1583      * @access private\r
1584      */\r
1585     function inline_crypt_setup()\r
1586     {\r
1587         // Note: inline_crypt_setup() will be called only if $this->changed === true\r
1588         // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().\r
1589         // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.\r
1590 \r
1591         $lambda_functions =& Crypt_Rijndael::get_lambda_functions();\r
1592         $block_size = $this->block_size;\r
1593         $mode = $this->mode;\r
1594 \r
1595         // The first 5 generated $lambda_functions will use the key-words hardcoded for better performance. \r
1596         // For memory reason we limit those ultra-optimized function code to 5.\r
1597         // After that, we use pure (extracted) integer vars for the key-words which is faster than accessing them via array.\r
1598         if (count($lambda_functions) < 5) {\r
1599             $w  = $this->w;\r
1600             $dw = $this->dw;\r
1601             $init_encryptBlock = '';\r
1602             $init_decryptBlock = '';\r
1603         } else {\r
1604             for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {\r
1605                 $w[]  = '$w_'.$i;\r
1606                 $dw[] = '$dw_'.$i;\r
1607             }\r
1608             $init_encryptBlock = 'extract($self->w,  EXTR_PREFIX_ALL, "w");';\r
1609             $init_decryptBlock = 'extract($self->dw, EXTR_PREFIX_ALL, "dw");';\r
1610         }\r
1611 \r
1612         $code_hash = md5("$mode, $block_size, " . implode(',', $w));\r
1613 \r
1614         if (!isset($lambda_functions[$code_hash])) {\r
1615             $Nr = $this->Nr;\r
1616             $Nb = $this->Nb;\r
1617             $c  = $this->c;\r
1618 \r
1619             // Generating encrypt code:\r
1620             $init_encryptBlock.= '\r
1621                 $t0 = $self->t0;\r
1622                 $t1 = $self->t1;\r
1623                 $t2 = $self->t2;\r
1624                 $t3 = $self->t3;\r
1625                 $sbox = $self->sbox;';\r
1626 \r
1627             $s  = 'e';\r
1628             $e  = 's';\r
1629             $wc = $Nb - 1;\r
1630 \r
1631             // Preround: addRoundKey\r
1632             $_encryptBlock = '$in = unpack("N*", $in);'."\n";\r
1633             for ($i = 0; $i < $Nb; ++$i) {\r
1634                 $_encryptBlock .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";\r
1635             }\r
1636 \r
1637             // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey\r
1638             for ($round = 1; $round < $Nr; ++$round) {\r
1639                 list($s, $e) = array($e, $s);\r
1640                 for ($i = 0; $i < $Nb; ++$i) {\r
1641                     $_encryptBlock.=\r
1642                         '$'.$e.$i.' =\r
1643                         $t0[($'.$s.$i                  .' >> 24) & 0xff] ^\r
1644                         $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^\r
1645                         $t2[($'.$s.(($i + $c[2]) % $Nb).' >>  8) & 0xff] ^\r
1646                         $t3[ $'.$s.(($i + $c[3]) % $Nb).'        & 0xff] ^\r
1647                         '.$w[++$wc].";\n";\r
1648                 }\r
1649             }\r
1650 \r
1651             // Finalround: subWord + shiftRows + addRoundKey\r
1652             for ($i = 0; $i < $Nb; ++$i) {\r
1653                 $_encryptBlock.=\r
1654                     '$'.$e.$i.' =\r
1655                      $sbox[ $'.$e.$i.'        & 0xff]        |\r
1656                     ($sbox[($'.$e.$i.' >>  8) & 0xff] <<  8) |\r
1657                     ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |\r
1658                     ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";\r
1659             }\r
1660             $_encryptBlock .= '$in = pack("N*"'."\n";\r
1661             for ($i = 0; $i < $Nb; ++$i) {\r
1662                 $_encryptBlock.= ',\r
1663                     ($'.$e.$i                  .' & 0xFF000000) ^\r
1664                     ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000) ^\r
1665                     ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00) ^\r
1666                     ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF) ^\r
1667                     '.$w[$i]."\n";\r
1668             }\r
1669             $_encryptBlock .= ');';\r
1670 \r
1671             // Generating decrypt code:\r
1672             $init_decryptBlock.= '\r
1673                 $dt0 = $self->dt0;\r
1674                 $dt1 = $self->dt1;\r
1675                 $dt2 = $self->dt2;\r
1676                 $dt3 = $self->dt3;\r
1677                 $isbox = $self->isbox;';\r
1678 \r
1679             $s  = 'e';\r
1680             $e  = 's';\r
1681             $wc = $Nb - 1;\r
1682 \r
1683             // Preround: addRoundKey\r
1684             $_decryptBlock = '$in = unpack("N*", $in);'."\n";\r
1685             for ($i = 0; $i < $Nb; ++$i) {\r
1686                 $_decryptBlock .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";\r
1687             }\r
1688 \r
1689             // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey\r
1690             for ($round = 1; $round < $Nr; ++$round) {\r
1691                 list($s, $e) = array($e, $s);\r
1692                 for ($i = 0; $i < $Nb; ++$i) {\r
1693                     $_decryptBlock.=\r
1694                         '$'.$e.$i.' =\r
1695                         $dt0[($'.$s.$i                        .' >> 24) & 0xff] ^\r
1696                         $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^\r
1697                         $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >>  8) & 0xff] ^\r
1698                         $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).'        & 0xff] ^\r
1699                         '.$dw[++$wc].";\n";\r
1700                 }\r
1701             }\r
1702 \r
1703             // Finalround: subWord + shiftRows + addRoundKey\r
1704             for ($i = 0; $i < $Nb; ++$i) {\r
1705                 $_decryptBlock.=\r
1706                     '$'.$e.$i.' =\r
1707                      $isbox[ $'.$e.$i.'        & 0xff]        |\r
1708                     ($isbox[($'.$e.$i.' >>  8) & 0xff] <<  8) |\r
1709                     ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |\r
1710                     ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";\r
1711             }\r
1712             $_decryptBlock .= '$in = pack("N*"'."\n";\r
1713             for ($i = 0; $i < $Nb; ++$i) {\r
1714                 $_decryptBlock.= ',\r
1715                     ($'.$e.$i.                        ' & 0xFF000000) ^\r
1716                     ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000) ^\r
1717                     ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00) ^\r
1718                     ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF) ^\r
1719                     '.$dw[$i]."\n";\r
1720             }\r
1721             $_decryptBlock .= ');';\r
1722 \r
1723             // Generating mode of operation code:\r
1724             switch ($mode) {\r
1725                 case CRYPT_RIJNDAEL_MODE_ECB:\r
1726                     $encrypt = $init_encryptBlock . '\r
1727                         $ciphertext = "";\r
1728                         $text = $self->_pad($text);\r
1729                         $plaintext_len = strlen($text);\r
1730 \r
1731                         for ($i = 0; $i < $plaintext_len; $i+= '.$block_size.') {\r
1732                             $in = substr($text, $i, '.$block_size.');\r
1733                             '.$_encryptBlock.'\r
1734                             $ciphertext.= $in;\r
1735                         }\r
1736                        \r
1737                         return $ciphertext;\r
1738                         ';\r
1739 \r
1740                     $decrypt = $init_decryptBlock . '\r
1741                         $plaintext = "";\r
1742                         $text = str_pad($text, strlen($text) + ('.$block_size.' - strlen($text) % '.$block_size.') % '.$block_size.', chr(0));\r
1743                         $ciphertext_len = strlen($text);\r
1744 \r
1745                         for ($i = 0; $i < $ciphertext_len; $i+= '.$block_size.') {\r
1746                             $in = substr($text, $i, '.$block_size.');\r
1747                             '.$_decryptBlock.'\r
1748                             $plaintext.= $in;\r
1749                         }\r
1750 \r
1751                         return $self->_unpad($plaintext);\r
1752                         ';\r
1753                     break;\r
1754                 case CRYPT_RIJNDAEL_MODE_CBC:\r
1755                     $encrypt = $init_encryptBlock . '\r
1756                         $ciphertext = "";\r
1757                         $text = $self->_pad($text);\r
1758                         $plaintext_len = strlen($text);\r
1759 \r
1760                         $in = $self->encryptIV;\r
1761 \r
1762                         for ($i = 0; $i < $plaintext_len; $i+= '.$block_size.') {\r
1763                             $in = substr($text, $i, '.$block_size.') ^ $in;\r
1764                             '.$_encryptBlock.'\r
1765                             $ciphertext.= $in;\r
1766                         }\r
1767 \r
1768                         if ($self->continuousBuffer) {\r
1769                             $self->encryptIV = $in;\r
1770                         }\r
1771 \r
1772                         return $ciphertext;\r
1773                         ';\r
1774 \r
1775                     $decrypt = $init_decryptBlock . '\r
1776                         $plaintext = "";\r
1777                         $text = str_pad($text, strlen($text) + ('.$block_size.' - strlen($text) % '.$block_size.') % '.$block_size.', chr(0));\r
1778                         $ciphertext_len = strlen($text);\r
1779 \r
1780                         $iv = $self->decryptIV;\r
1781 \r
1782                         for ($i = 0; $i < $ciphertext_len; $i+= '.$block_size.') {\r
1783                             $in = $block = substr($text, $i, '.$block_size.');\r
1784                             '.$_decryptBlock.'\r
1785                             $plaintext.= $in ^ $iv;\r
1786                             $iv = $block;\r
1787                         }\r
1788 \r
1789                         if ($self->continuousBuffer) {\r
1790                             $self->decryptIV = $iv;\r
1791                         }\r
1792 \r
1793                         return $self->_unpad($plaintext);\r
1794                         ';\r
1795                     break;\r
1796                 case CRYPT_RIJNDAEL_MODE_CTR:\r
1797                     $encrypt = $init_encryptBlock . '\r
1798                         $ciphertext = "";\r
1799                         $plaintext_len = strlen($text);\r
1800                         $xor = $self->encryptIV;\r
1801                         $buffer = &$self->enbuffer;\r
1802 \r
1803                         if (strlen($buffer["encrypted"])) {\r
1804                             for ($i = 0; $i < $plaintext_len; $i+= '.$block_size.') {\r
1805                                 $block = substr($text, $i, '.$block_size.');\r
1806                                 if (strlen($block) > strlen($buffer["encrypted"])) {\r
1807                                     $in = $self->_generate_xor('.$block_size.', $xor);\r
1808                                     '.$_encryptBlock.'\r
1809                                     $buffer["encrypted"].= $in;\r
1810                                 }\r
1811                                 $key = $self->_string_shift($buffer["encrypted"], '.$block_size.');\r
1812                                 $ciphertext.= $block ^ $key;\r
1813                             }\r
1814                         } else {\r
1815                             for ($i = 0; $i < $plaintext_len; $i+= '.$block_size.') {\r
1816                                 $block = substr($text, $i, '.$block_size.');\r
1817                                 $in = $self->_generate_xor('.$block_size.', $xor);\r
1818                                 '.$_encryptBlock.'\r
1819                                 $key = $in;\r
1820                                 $ciphertext.= $block ^ $key;\r
1821                             }\r
1822                         }\r
1823                         if ($self->continuousBuffer) {\r
1824                             $self->encryptIV = $xor;\r
1825                             if ($start = $plaintext_len % '.$block_size.') {\r
1826                                 $buffer["encrypted"] = substr($key, $start) . $buffer["encrypted"];\r
1827                             }\r
1828                         }\r
1829 \r
1830                         return $ciphertext;\r
1831                     ';\r
1832 \r
1833                     $decrypt = $init_encryptBlock . '\r
1834                         $plaintext = "";\r
1835                         $ciphertext_len = strlen($text);\r
1836                         $xor = $self->decryptIV;\r
1837                         $buffer = &$self->debuffer;\r
1838 \r
1839                         if (strlen($buffer["ciphertext"])) {\r
1840                             for ($i = 0; $i < $ciphertext_len; $i+= '.$block_size.') {\r
1841                                 $block = substr($text, $i, '.$block_size.');\r
1842                                 if (strlen($block) > strlen($buffer["ciphertext"])) {\r
1843                                     $in = $self->_generate_xor('.$block_size.', $xor);\r
1844                                     '.$_encryptBlock.'\r
1845                                     $buffer["ciphertext"].= $in;\r
1846                                 }\r
1847                                 $key = $self->_string_shift($buffer["ciphertext"], '.$block_size.');\r
1848                                 $plaintext.= $block ^ $key;\r
1849                             }\r
1850                         } else {\r
1851                             for ($i = 0; $i < $ciphertext_len; $i+= '.$block_size.') {\r
1852                                 $block = substr($text, $i, '.$block_size.');\r
1853                                 $in = $self->_generate_xor('.$block_size.', $xor);\r
1854                                 '.$_encryptBlock.'\r
1855                                 $key = $in;\r
1856                                 $plaintext.= $block ^ $key;\r
1857                             }\r
1858                         }\r
1859                         if ($self->continuousBuffer) {\r
1860                             $self->decryptIV = $xor;\r
1861                             if ($start = $ciphertext_len % '.$block_size.') {\r
1862                                 $buffer["ciphertext"] = substr($key, $start) . $buffer["ciphertext"];\r
1863                             }\r
1864                         }\r
1865                        \r
1866                         return $plaintext;\r
1867                         ';\r
1868                     break;\r
1869                 case CRYPT_RIJNDAEL_MODE_CFB:\r
1870                     $encrypt = $init_encryptBlock . '\r
1871                         $ciphertext = "";\r
1872                         $buffer = &$self->enbuffer;\r
1873 \r
1874                         if ($self->continuousBuffer) {\r
1875                             $iv = &$self->encryptIV;\r
1876                             $pos = &$buffer["pos"];\r
1877                         } else {\r
1878                             $iv = $self->encryptIV;\r
1879                             $pos = 0;\r
1880                         }\r
1881                         $len = strlen($text);\r
1882                         $i = 0;\r
1883                         if ($pos) {\r
1884                             $orig_pos = $pos;\r
1885                             $max = '.$block_size.' - $pos;\r
1886                             if ($len >= $max) {\r
1887                                 $i = $max;\r
1888                                 $len-= $max;\r
1889                                 $pos = 0;\r
1890                             } else {\r
1891                                 $i = $len;\r
1892                                 $pos+= $len;\r
1893                                 $len = 0;\r
1894                             }\r
1895                             $ciphertext = substr($iv, $orig_pos) ^ $text;\r
1896                             $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);\r
1897                         }\r
1898                         while ($len >= '.$block_size.') {\r
1899                             $in = $iv;\r
1900                             '.$_encryptBlock.';\r
1901                             $iv = $in ^ substr($text, $i, '.$block_size.');\r
1902                             $ciphertext.= $iv;\r
1903                             $len-= '.$block_size.';\r
1904                             $i+= '.$block_size.';\r
1905                         }\r
1906                         if ($len) {\r
1907                             $in = $iv;\r
1908                             '.$_encryptBlock.'\r
1909                             $iv = $in;\r
1910                             $block = $iv ^ substr($text, $i);\r
1911                             $iv = substr_replace($iv, $block, 0, $len);\r
1912                             $ciphertext.= $block;\r
1913                             $pos = $len;\r
1914                         }\r
1915                         return $ciphertext;\r
1916                     ';\r
1917 \r
1918                     $decrypt = $init_encryptBlock . '\r
1919                         $plaintext = "";\r
1920                         $buffer = &$self->debuffer;\r
1921 \r
1922                         if ($self->continuousBuffer) {\r
1923                             $iv = &$self->decryptIV;\r
1924                             $pos = &$buffer["pos"];\r
1925                         } else {\r
1926                             $iv = $self->decryptIV;\r
1927                             $pos = 0;\r
1928                         }\r
1929                         $len = strlen($text);\r
1930                         $i = 0;\r
1931                         if ($pos) {\r
1932                             $orig_pos = $pos;\r
1933                             $max = '.$block_size.' - $pos;\r
1934                             if ($len >= $max) {\r
1935                                 $i = $max;\r
1936                                 $len-= $max;\r
1937                                 $pos = 0;\r
1938                             } else {\r
1939                                 $i = $len;\r
1940                                 $pos+= $len;\r
1941                                 $len = 0;\r
1942                             }\r
1943                             $plaintext = substr($iv, $orig_pos) ^ $text;\r
1944                             $iv = substr_replace($iv, substr($text, 0, $i), $orig_pos, $i);\r
1945                         }\r
1946                         while ($len >= '.$block_size.') {\r
1947                             $in = $iv;\r
1948                             '.$_encryptBlock.'\r
1949                             $iv = $in;\r
1950                             $cb = substr($text, $i, '.$block_size.');\r
1951                             $plaintext.= $iv ^ $cb;\r
1952                             $iv = $cb;\r
1953                             $len-= '.$block_size.';\r
1954                             $i+= '.$block_size.';\r
1955                         }\r
1956                         if ($len) {\r
1957                             $in = $iv;\r
1958                             '.$_encryptBlock.'\r
1959                             $iv = $in;\r
1960                             $plaintext.= $iv ^ substr($text, $i);\r
1961                             $iv = substr_replace($iv, substr($text, $i), 0, $len);\r
1962                             $pos = $len;\r
1963                         }\r
1964 \r
1965                         return $plaintext;\r
1966                         ';\r
1967                     break;\r
1968                 case CRYPT_RIJNDAEL_MODE_OFB:\r
1969                     $encrypt = $init_encryptBlock . '\r
1970                         $ciphertext = "";\r
1971                         $plaintext_len = strlen($text);\r
1972                         $xor = $self->encryptIV;\r
1973                         $buffer = &$self->enbuffer;\r
1974 \r
1975                         if (strlen($buffer["xor"])) {\r
1976                             for ($i = 0; $i < $plaintext_len; $i+= '.$block_size.') {\r
1977                                 $block = substr($text, $i, '.$block_size.');\r
1978                                 if (strlen($block) > strlen($buffer["xor"])) {\r
1979                                     $in = $xor;\r
1980                                     '.$_encryptBlock.'\r
1981                                     $xor = $in;\r
1982                                     $buffer["xor"].= $xor;\r
1983                                 }\r
1984                                 $key = $self->_string_shift($buffer["xor"], '.$block_size.');\r
1985                                 $ciphertext.= $block ^ $key;\r
1986                             }\r
1987                         } else {\r
1988                             for ($i = 0; $i < $plaintext_len; $i+= '.$block_size.') {\r
1989                                 $in = $xor;\r
1990                                 '.$_encryptBlock.'\r
1991                                 $xor = $in;\r
1992                                 $ciphertext.= substr($text, $i, '.$block_size.') ^ $xor;\r
1993                             }\r
1994                             $key = $xor;\r
1995                         }\r
1996                         if ($self->continuousBuffer) {\r
1997                             $self->encryptIV = $xor;\r
1998                             if ($start = $plaintext_len % '.$block_size.') {\r
1999                                  $buffer["xor"] = substr($key, $start) . $buffer["xor"];\r
2000                             }\r
2001                         }\r
2002                         return $ciphertext;\r
2003                         ';\r
2004 \r
2005                     $decrypt = $init_encryptBlock . '\r
2006                         $plaintext = "";\r
2007                         $ciphertext_len = strlen($text);\r
2008                         $xor = $self->decryptIV;\r
2009                         $buffer = &$self->debuffer;\r
2010 \r
2011                         if (strlen($buffer["xor"])) {\r
2012                             for ($i = 0; $i < $ciphertext_len; $i+= '.$block_size.') {\r
2013                                 $block = substr($text, $i, '.$block_size.');\r
2014                                 if (strlen($block) > strlen($buffer["xor"])) {\r
2015                                     $in = $xor;\r
2016                                     '.$_encryptBlock.'\r
2017                                     $xor = $in;\r
2018                                     $buffer["xor"].= $xor;\r
2019                                 }\r
2020                                 $key = $self->_string_shift($buffer["xor"], '.$block_size.');\r
2021                                 $plaintext.= $block ^ $key;\r
2022                             }\r
2023                         } else {\r
2024                             for ($i = 0; $i < $ciphertext_len; $i+= '.$block_size.') {\r
2025                                 $in = $xor;\r
2026                                 '.$_encryptBlock.'\r
2027                                 $xor = $in;\r
2028                                 $plaintext.= substr($text, $i, '.$block_size.') ^ $xor;\r
2029                             }\r
2030                             $key = $xor;\r
2031                         }\r
2032                         if ($self->continuousBuffer) {\r
2033                             $self->decryptIV = $xor;\r
2034                             if ($start = $ciphertext_len % '.$block_size.') {\r
2035                                  $buffer["xor"] = substr($key, $start) . $buffer["xor"];\r
2036                             }\r
2037                         }\r
2038                         return $plaintext;\r
2039                         ';\r
2040                     break;\r
2041             }\r
2042             $lambda_functions[$code_hash] = create_function('$action, &$self, $text', 'if ($action == "encrypt") { '.$encrypt.' } else { '.$decrypt.' }');\r
2043         }\r
2044         $this->inline_crypt = $lambda_functions[$code_hash];\r
2045     }\r
2046 \r
2047     /**\r
2048      * Holds the lambda_functions table (classwide)\r
2049      *\r
2050      * @see Crypt_Rijndael::inline_crypt_setup()\r
2051      * @return Array\r
2052      * @access private\r
2053      */\r
2054     function &get_lambda_functions()\r
2055     {\r
2056         static $functions = array();\r
2057         return $functions;\r
2058     }\r
2059 }\r
2060 \r
2061 // vim: ts=4:sw=4:et:\r
2062 // vim6: fdl=1:\r