]> git.mxchange.org Git - friendica.git/blob - library/phpsec/Crypt/TripleDES.php
make 'PHP "register_argc_argv"' easier to translate, may require fix for po2php
[friendica.git] / library / phpsec / Crypt / TripleDES.php
1 <?php\r
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */\r
3 \r
4 /**\r
5  * Pure-PHP implementation of Triple DES.\r
6  *\r
7  * Uses mcrypt, if available, and an internal implementation, otherwise.  Operates in the EDE3 mode (encrypt-decrypt-encrypt).\r
8  *\r
9  * PHP versions 4 and 5\r
10  *\r
11  * Here's a short example of how to use this library:\r
12  * <code>\r
13  * <?php\r
14  *    include('Crypt/TripleDES.php');\r
15  *\r
16  *    $des = new Crypt_TripleDES();\r
17  *\r
18  *    $des->setKey('abcdefghijklmnopqrstuvwx');\r
19  *\r
20  *    $size = 10 * 1024;\r
21  *    $plaintext = '';\r
22  *    for ($i = 0; $i < $size; $i++) {\r
23  *        $plaintext.= 'a';\r
24  *    }\r
25  *\r
26  *    echo $des->decrypt($des->encrypt($plaintext));\r
27  * ?>\r
28  * </code>\r
29  *\r
30  * LICENSE: This library is free software; you can redistribute it and/or\r
31  * modify it under the terms of the GNU Lesser General Public\r
32  * License as published by the Free Software Foundation; either\r
33  * version 2.1 of the License, or (at your option) any later version.\r
34  *\r
35  * This library is distributed in the hope that it will be useful,\r
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
38  * Lesser General Public License for more details.\r
39  *\r
40  * You should have received a copy of the GNU Lesser General Public\r
41  * License along with this library; if not, write to the Free Software\r
42  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,\r
43  * MA  02111-1307  USA\r
44  *\r
45  * @category   Crypt\r
46  * @package    Crypt_TripleDES\r
47  * @author     Jim Wigginton <terrafrost@php.net>\r
48  * @copyright  MMVII Jim Wigginton\r
49  * @license    http://www.gnu.org/licenses/lgpl.txt\r
50  * @version    $Id: TripleDES.php,v 1.13 2010/02/26 03:40:25 terrafrost Exp $\r
51  * @link       http://phpseclib.sourceforge.net\r
52  */\r
53 \r
54 /**\r
55  * Include Crypt_DES\r
56  */\r
57 require_once 'DES.php';\r
58 \r
59 /**\r
60  * Encrypt / decrypt using inner chaining\r
61  *\r
62  * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).\r
63  */\r
64 define('CRYPT_DES_MODE_3CBC', 3);\r
65 \r
66 /**\r
67  * Encrypt / decrypt using outer chaining\r
68  *\r
69  * Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.\r
70  */\r
71 define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);\r
72 \r
73 /**\r
74  * Pure-PHP implementation of Triple DES.\r
75  *\r
76  * @author  Jim Wigginton <terrafrost@php.net>\r
77  * @version 0.1.0\r
78  * @access  public\r
79  * @package Crypt_TerraDES\r
80  */\r
81 class Crypt_TripleDES {\r
82     /**\r
83      * The Three Keys\r
84      *\r
85      * @see Crypt_TripleDES::setKey()\r
86      * @var String\r
87      * @access private\r
88      */\r
89     var $key = "\0\0\0\0\0\0\0\0";\r
90 \r
91     /**\r
92      * The Encryption Mode\r
93      *\r
94      * @see Crypt_TripleDES::Crypt_TripleDES()\r
95      * @var Integer\r
96      * @access private\r
97      */\r
98     var $mode = CRYPT_DES_MODE_CBC;\r
99 \r
100     /**\r
101      * Continuous Buffer status\r
102      *\r
103      * @see Crypt_TripleDES::enableContinuousBuffer()\r
104      * @var Boolean\r
105      * @access private\r
106      */\r
107     var $continuousBuffer = false;\r
108 \r
109     /**\r
110      * Padding status\r
111      *\r
112      * @see Crypt_TripleDES::enablePadding()\r
113      * @var Boolean\r
114      * @access private\r
115      */\r
116     var $padding = true;\r
117 \r
118     /**\r
119      * The Initialization Vector\r
120      *\r
121      * @see Crypt_TripleDES::setIV()\r
122      * @var String\r
123      * @access private\r
124      */\r
125     var $iv = "\0\0\0\0\0\0\0\0";\r
126 \r
127     /**\r
128      * A "sliding" Initialization Vector\r
129      *\r
130      * @see Crypt_TripleDES::enableContinuousBuffer()\r
131      * @var String\r
132      * @access private\r
133      */\r
134     var $encryptIV = "\0\0\0\0\0\0\0\0";\r
135 \r
136     /**\r
137      * A "sliding" Initialization Vector\r
138      *\r
139      * @see Crypt_TripleDES::enableContinuousBuffer()\r
140      * @var String\r
141      * @access private\r
142      */\r
143     var $decryptIV = "\0\0\0\0\0\0\0\0";\r
144 \r
145     /**\r
146      * The Crypt_DES objects\r
147      *\r
148      * @var Array\r
149      * @access private\r
150      */\r
151     var $des;\r
152 \r
153     /**\r
154      * mcrypt resource for encryption\r
155      *\r
156      * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.\r
157      * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.\r
158      *\r
159      * @see Crypt_AES::encrypt()\r
160      * @var String\r
161      * @access private\r
162      */\r
163     var $enmcrypt;\r
164 \r
165     /**\r
166      * mcrypt resource for decryption\r
167      *\r
168      * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.\r
169      * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.\r
170      *\r
171      * @see Crypt_AES::decrypt()\r
172      * @var String\r
173      * @access private\r
174      */\r
175     var $demcrypt;\r
176 \r
177     /**\r
178      * Does the (en|de)mcrypt resource need to be (re)initialized?\r
179      *\r
180      * @see setKey()\r
181      * @see setIV()\r
182      * @var Boolean\r
183      * @access private\r
184      */\r
185     var $changed = true;\r
186 \r
187     /**\r
188      * Default Constructor.\r
189      *\r
190      * Determines whether or not the mcrypt extension should be used.  $mode should only, at present, be\r
191      * CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC.  If not explictly set, CRYPT_DES_MODE_CBC will be used.\r
192      *\r
193      * @param optional Integer $mode\r
194      * @return Crypt_TripleDES\r
195      * @access public\r
196      */\r
197     function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC)\r
198     {\r
199         if ( !defined('CRYPT_DES_MODE') ) {\r
200             switch (true) {\r
201                 case extension_loaded('mcrypt'):\r
202                     // i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),\r
203                     // but since that can be changed after the object has been created, there doesn't seem to be\r
204                     // a lot of point...\r
205                     define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);\r
206                     break;\r
207                 default:\r
208                     define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);\r
209             }\r
210         }\r
211 \r
212         if ( $mode == CRYPT_DES_MODE_3CBC ) {\r
213             $this->mode = CRYPT_DES_MODE_3CBC;\r
214             $this->des = array(\r
215                 new Crypt_DES(CRYPT_DES_MODE_CBC),\r
216                 new Crypt_DES(CRYPT_DES_MODE_CBC),\r
217                 new Crypt_DES(CRYPT_DES_MODE_CBC)\r
218             );\r
219 \r
220             // we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects\r
221             $this->des[0]->disablePadding();\r
222             $this->des[1]->disablePadding();\r
223             $this->des[2]->disablePadding();\r
224 \r
225             return;\r
226         }\r
227 \r
228         switch ( CRYPT_DES_MODE ) {\r
229             case CRYPT_DES_MODE_MCRYPT:\r
230                 switch ($mode) {\r
231                     case CRYPT_DES_MODE_ECB:\r
232                         $this->mode = MCRYPT_MODE_ECB;\r
233                         break;\r
234                     case CRYPT_DES_MODE_CTR:\r
235                         $this->mode = 'ctr';\r
236                         break;\r
237                     case CRYPT_DES_MODE_CBC:\r
238                     default:\r
239                         $this->mode = MCRYPT_MODE_CBC;\r
240                 }\r
241 \r
242                 break;\r
243             default:\r
244                 $this->des = array(\r
245                     new Crypt_DES(CRYPT_DES_MODE_ECB),\r
246                     new Crypt_DES(CRYPT_DES_MODE_ECB),\r
247                     new Crypt_DES(CRYPT_DES_MODE_ECB)\r
248                 );\r
249  \r
250                 // we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects\r
251                 $this->des[0]->disablePadding();\r
252                 $this->des[1]->disablePadding();\r
253                 $this->des[2]->disablePadding();\r
254 \r
255                 switch ($mode) {\r
256                     case CRYPT_DES_MODE_ECB:\r
257                     case CRYPT_DES_MODE_CTR:\r
258                     case CRYPT_DES_MODE_CBC:\r
259                         $this->mode = $mode;\r
260                         break;\r
261                     default:\r
262                         $this->mode = CRYPT_DES_MODE_CBC;\r
263                 }\r
264         }\r
265     }\r
266 \r
267     /**\r
268      * Sets the key.\r
269      *\r
270      * Keys can be of any length.  Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or\r
271      * 192-bit (eg. strlen($key) == 24) keys.  This function pads and truncates $key as appropriate.\r
272      *\r
273      * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.\r
274      *\r
275      * If the key is not explicitly set, it'll be assumed to be all zero's.\r
276      *\r
277      * @access public\r
278      * @param String $key\r
279      */\r
280     function setKey($key)\r
281     {\r
282         $length = strlen($key);\r
283         if ($length > 8) {\r
284             $key = str_pad($key, 24, chr(0));\r
285             // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:\r
286             // http://php.net/function.mcrypt-encrypt#47973\r
287             //$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);\r
288         }\r
289         $this->key = $key;\r
290         switch (true) {\r
291             case CRYPT_DES_MODE == CRYPT_DES_MODE_INTERNAL:\r
292             case $this->mode == CRYPT_DES_MODE_3CBC:\r
293                 $this->des[0]->setKey(substr($key,  0, 8));\r
294                 $this->des[1]->setKey(substr($key,  8, 8));\r
295                 $this->des[2]->setKey(substr($key, 16, 8));\r
296         }\r
297         $this->changed = true;\r
298     }\r
299 \r
300     /**\r
301      * Sets the initialization vector. (optional)\r
302      *\r
303      * SetIV is not required when CRYPT_DES_MODE_ECB is being used.  If not explictly set, it'll be assumed\r
304      * to be all zero's.\r
305      *\r
306      * @access public\r
307      * @param String $iv\r
308      */\r
309     function setIV($iv)\r
310     {\r
311         $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));\r
312         if ($this->mode == CRYPT_DES_MODE_3CBC) {\r
313             $this->des[0]->setIV($iv);\r
314             $this->des[1]->setIV($iv);\r
315             $this->des[2]->setIV($iv);\r
316         }\r
317         $this->changed = true;\r
318     }\r
319 \r
320     /**\r
321      * Generate CTR XOR encryption key\r
322      *\r
323      * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the\r
324      * plaintext / ciphertext in CTR mode.\r
325      *\r
326      * @see Crypt_DES::decrypt()\r
327      * @see Crypt_DES::encrypt()\r
328      * @access public\r
329      * @param Integer $length\r
330      * @param String $iv\r
331      */\r
332     function _generate_xor($length, &$iv)\r
333     {\r
334         $xor = '';\r
335         $num_blocks = ($length + 7) >> 3;\r
336         for ($i = 0; $i < $num_blocks; $i++) {\r
337             $xor.= $iv;\r
338             for ($j = 4; $j <= 8; $j+=4) {\r
339                 $temp = substr($iv, -$j, 4);\r
340                 switch ($temp) {\r
341                     case "\xFF\xFF\xFF\xFF":\r
342                         $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);\r
343                         break;\r
344                     case "\x7F\xFF\xFF\xFF":\r
345                         $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);\r
346                         break 2;\r
347                     default:\r
348                         extract(unpack('Ncount', $temp));\r
349                         $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);\r
350                         break 2;\r
351                 }\r
352             }\r
353         }\r
354 \r
355         return $xor;\r
356     }\r
357 \r
358     /**\r
359      * Encrypts a message.\r
360      *\r
361      * @access public\r
362      * @param String $plaintext\r
363      */\r
364     function encrypt($plaintext)\r
365     {\r
366         if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {\r
367             $plaintext = $this->_pad($plaintext);\r
368         }\r
369 \r
370         // if the key is smaller then 8, do what we'd normally do\r
371         if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {\r
372             $ciphertext = $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($plaintext)));\r
373 \r
374             return $ciphertext;\r
375         }\r
376 \r
377         if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {\r
378             if ($this->changed) {\r
379                 if (!isset($this->enmcrypt)) {\r
380                     $this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');\r
381                 }\r
382                 mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);\r
383                 $this->changed = false;\r
384             }\r
385 \r
386             $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);\r
387 \r
388             if (!$this->continuousBuffer) {\r
389                 mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);\r
390             }\r
391 \r
392             return $ciphertext;\r
393         }\r
394 \r
395         if (strlen($this->key) <= 8) {\r
396             $this->des[0]->mode = $this->mode;\r
397 \r
398             return $this->des[0]->encrypt($plaintext);\r
399         }\r
400 \r
401         // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :\r
402         // "The data is padded with "\0" to make sure the length of the data is n * blocksize."\r
403         $plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));\r
404 \r
405         $des = $this->des;\r
406 \r
407         $ciphertext = '';\r
408         switch ($this->mode) {\r
409             case CRYPT_DES_MODE_ECB:\r
410                 for ($i = 0; $i < strlen($plaintext); $i+=8) {\r
411                     $block = substr($plaintext, $i, 8);\r
412                     $block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
413                     $block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);\r
414                     $block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
415                     $ciphertext.= $block;\r
416                 }\r
417                 break;\r
418             case CRYPT_DES_MODE_CBC:\r
419                 $xor = $this->encryptIV;\r
420                 for ($i = 0; $i < strlen($plaintext); $i+=8) {\r
421                     $block = substr($plaintext, $i, 8) ^ $xor;\r
422                     $block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
423                     $block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);\r
424                     $block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
425                     $xor = $block;\r
426                     $ciphertext.= $block;\r
427                 }\r
428                 if ($this->continuousBuffer) {\r
429                     $this->encryptIV = $xor;\r
430                 }\r
431                 break;\r
432             case CRYPT_DES_MODE_CTR:\r
433                 $xor = $this->encryptIV;\r
434                 for ($i = 0; $i < strlen($plaintext); $i+=8) {\r
435                     $key = $this->_generate_xor(8, $xor);\r
436                     $key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);\r
437                     $key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);\r
438                     $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);\r
439                     $block = substr($plaintext, $i, 8);\r
440                     $ciphertext.= $block ^ $key;\r
441                 }\r
442                 if ($this->continuousBuffer) {\r
443                     $this->encryptIV = $xor;\r
444                 }\r
445         }\r
446 \r
447         return $ciphertext;\r
448     }\r
449 \r
450     /**\r
451      * Decrypts a message.\r
452      *\r
453      * @access public\r
454      * @param String $ciphertext\r
455      */\r
456     function decrypt($ciphertext)\r
457     {\r
458         if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {\r
459             $plaintext = $this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt($ciphertext)));\r
460 \r
461             return $this->_unpad($plaintext);\r
462         }\r
463 \r
464         // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :\r
465         // "The data is padded with "\0" to make sure the length of the data is n * blocksize."\r
466         $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));\r
467 \r
468         if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {\r
469             if ($this->changed) {\r
470                 if (!isset($this->demcrypt)) {\r
471                     $this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');\r
472                 }\r
473                 mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);\r
474                 $this->changed = false;\r
475             }\r
476 \r
477             $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);\r
478 \r
479             if (!$this->continuousBuffer) {\r
480                 mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);\r
481             }\r
482 \r
483             return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;\r
484         }\r
485 \r
486         if (strlen($this->key) <= 8) {\r
487             $this->des[0]->mode = $this->mode;\r
488 \r
489             return $this->_unpad($this->des[0]->decrypt($plaintext));\r
490         }\r
491 \r
492         $des = $this->des;\r
493 \r
494         $plaintext = '';\r
495         switch ($this->mode) {\r
496             case CRYPT_DES_MODE_ECB:\r
497                 for ($i = 0; $i < strlen($ciphertext); $i+=8) {\r
498                     $block = substr($ciphertext, $i, 8);\r
499                     $block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);\r
500                     $block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
501                     $block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);\r
502                     $plaintext.= $block;\r
503                 }\r
504                 break;\r
505             case CRYPT_DES_MODE_CBC:\r
506                 $xor = $this->decryptIV;\r
507                 for ($i = 0; $i < strlen($ciphertext); $i+=8) {\r
508                     $orig = $block = substr($ciphertext, $i, 8);\r
509                     $block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);\r
510                     $block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
511                     $block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);\r
512                     $plaintext.= $block ^ $xor;\r
513                     $xor = $orig;\r
514                 }\r
515                 if ($this->continuousBuffer) {\r
516                     $this->decryptIV = $xor;\r
517                 }\r
518                 break;\r
519             case CRYPT_DES_MODE_CTR:\r
520                 $xor = $this->decryptIV;\r
521                 for ($i = 0; $i < strlen($ciphertext); $i+=8) {\r
522                     $key = $this->_generate_xor(8, $xor);\r
523                     $key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);\r
524                     $key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);\r
525                     $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);\r
526                     $block = substr($ciphertext, $i, 8);\r
527                     $plaintext.= $block ^ $key;\r
528                 }\r
529                 if ($this->continuousBuffer) {\r
530                     $this->decryptIV = $xor;\r
531                 }\r
532         }\r
533 \r
534         return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;\r
535     }\r
536 \r
537     /**\r
538      * Treat consecutive "packets" as if they are a continuous buffer.\r
539      *\r
540      * Say you have a 16-byte plaintext $plaintext.  Using the default behavior, the two following code snippets\r
541      * will yield different outputs:\r
542      *\r
543      * <code>\r
544      *    echo $des->encrypt(substr($plaintext, 0, 8));\r
545      *    echo $des->encrypt(substr($plaintext, 8, 8));\r
546      * </code>\r
547      * <code>\r
548      *    echo $des->encrypt($plaintext);\r
549      * </code>\r
550      *\r
551      * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates\r
552      * another, as demonstrated with the following:\r
553      *\r
554      * <code>\r
555      *    $des->encrypt(substr($plaintext, 0, 8));\r
556      *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));\r
557      * </code>\r
558      * <code>\r
559      *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));\r
560      * </code>\r
561      *\r
562      * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different\r
563      * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /\r
564      * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.\r
565      *\r
566      * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each\r
567      * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that\r
568      * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),\r
569      * however, they are also less intuitive and more likely to cause you problems.\r
570      *\r
571      * @see Crypt_TripleDES::disableContinuousBuffer()\r
572      * @access public\r
573      */\r
574     function enableContinuousBuffer()\r
575     {\r
576         $this->continuousBuffer = true;\r
577         if ($this->mode == CRYPT_DES_MODE_3CBC) {\r
578             $this->des[0]->enableContinuousBuffer();\r
579             $this->des[1]->enableContinuousBuffer();\r
580             $this->des[2]->enableContinuousBuffer();\r
581         }\r
582     }\r
583 \r
584     /**\r
585      * Treat consecutive packets as if they are a discontinuous buffer.\r
586      *\r
587      * The default behavior.\r
588      *\r
589      * @see Crypt_TripleDES::enableContinuousBuffer()\r
590      * @access public\r
591      */\r
592     function disableContinuousBuffer()\r
593     {\r
594         $this->continuousBuffer = false;\r
595         $this->encryptIV = $this->iv;\r
596         $this->decryptIV = $this->iv;\r
597 \r
598         if ($this->mode == CRYPT_DES_MODE_3CBC) {\r
599             $this->des[0]->disableContinuousBuffer();\r
600             $this->des[1]->disableContinuousBuffer();\r
601             $this->des[2]->disableContinuousBuffer();\r
602         }\r
603     }\r
604 \r
605     /**\r
606      * Pad "packets".\r
607      *\r
608      * DES works by encrypting eight bytes at a time.  If you ever need to encrypt or decrypt something that's not\r
609      * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.\r
610      *\r
611      * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH1,\r
612      * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping\r
613      * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is\r
614      * transmitted separately)\r
615      *\r
616      * @see Crypt_TripleDES::disablePadding()\r
617      * @access public\r
618      */\r
619     function enablePadding()\r
620     {\r
621         $this->padding = true;\r
622     }\r
623 \r
624     /**\r
625      * Do not pad packets.\r
626      *\r
627      * @see Crypt_TripleDES::enablePadding()\r
628      * @access public\r
629      */\r
630     function disablePadding()\r
631     {\r
632         $this->padding = false;\r
633     }\r
634 \r
635     /**\r
636      * Pads a string\r
637      *\r
638      * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).\r
639      * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)\r
640      *\r
641      * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless\r
642      * and padding will, hence forth, be enabled.\r
643      *\r
644      * @see Crypt_TripleDES::_unpad()\r
645      * @access private\r
646      */\r
647     function _pad($text)\r
648     {\r
649         $length = strlen($text);\r
650 \r
651         if (!$this->padding) {\r
652             if (($length & 7) == 0) {\r
653                 return $text;\r
654             } else {\r
655                 user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);\r
656                 $this->padding = true;\r
657             }\r
658         }\r
659 \r
660         $pad = 8 - ($length & 7);\r
661         return str_pad($text, $length + $pad, chr($pad));\r
662     }\r
663 \r
664     /**\r
665      * Unpads a string\r
666      *\r
667      * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong\r
668      * and false will be returned.\r
669      *\r
670      * @see Crypt_TripleDES::_pad()\r
671      * @access private\r
672      */\r
673     function _unpad($text)\r
674     {\r
675         if (!$this->padding) {\r
676             return $text;\r
677         }\r
678 \r
679         $length = ord($text[strlen($text) - 1]);\r
680 \r
681         if (!$length || $length > 8) {\r
682             return false;\r
683         }\r
684 \r
685         return substr($text, 0, -$length);\r
686     }\r
687 }\r
688 \r
689 // vim: ts=4:sw=4:et:\r
690 // vim6: fdl=1: