]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/OStatus/extlib/Crypt/TripleDES.php
Adding Crypt library from http://phpseclib.sourceforge.net/
[quix0rs-gnu-social.git] / plugins / OStatus / extlib / 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.9 2009/11/23 19:06:07 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      * MCrypt parameters\r
147      *\r
148      * @see Crypt_TripleDES::setMCrypt()\r
149      * @var Array\r
150      * @access private\r
151      */\r
152     var $mcrypt = array('', '');\r
153 \r
154     /**\r
155      * The Crypt_DES objects\r
156      *\r
157      * @var Array\r
158      * @access private\r
159      */\r
160     var $des;\r
161 \r
162     /**\r
163      * Default Constructor.\r
164      *\r
165      * Determines whether or not the mcrypt extension should be used.  $mode should only, at present, be\r
166      * CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC.  If not explictly set, CRYPT_DES_MODE_CBC will be used.\r
167      *\r
168      * @param optional Integer $mode\r
169      * @return Crypt_TripleDES\r
170      * @access public\r
171      */\r
172     function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC)\r
173     {\r
174         if ( !defined('CRYPT_DES_MODE') ) {\r
175             switch (true) {\r
176                 case extension_loaded('mcrypt'):\r
177                     // i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),\r
178                     // but since that can be changed after the object has been created, there doesn't seem to be\r
179                     // a lot of point...\r
180                     define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);\r
181                     break;\r
182                 default:\r
183                     define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);\r
184             }\r
185         }\r
186 \r
187         if ( $mode == CRYPT_DES_MODE_3CBC ) {\r
188             $this->mode = CRYPT_DES_MODE_3CBC;\r
189             $this->des = array(\r
190                 new Crypt_DES(CRYPT_DES_MODE_CBC),\r
191                 new Crypt_DES(CRYPT_DES_MODE_CBC),\r
192                 new Crypt_DES(CRYPT_DES_MODE_CBC)\r
193             );\r
194 \r
195             // we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects\r
196             $this->des[0]->disablePadding();\r
197             $this->des[1]->disablePadding();\r
198             $this->des[2]->disablePadding();\r
199 \r
200             return;\r
201         }\r
202 \r
203         switch ( CRYPT_DES_MODE ) {\r
204             case CRYPT_DES_MODE_MCRYPT:\r
205                 switch ($mode) {\r
206                     case CRYPT_DES_MODE_ECB:\r
207                         $this->mode = MCRYPT_MODE_ECB;    break;\r
208                     case CRYPT_DES_MODE_CBC:\r
209                     default:\r
210                         $this->mode = MCRYPT_MODE_CBC;\r
211                 }\r
212 \r
213                 break;\r
214             default:\r
215                 $this->des = array(\r
216                     new Crypt_DES(CRYPT_DES_MODE_ECB),\r
217                     new Crypt_DES(CRYPT_DES_MODE_ECB),\r
218                     new Crypt_DES(CRYPT_DES_MODE_ECB)\r
219                 );\r
220  \r
221                 // we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects\r
222                 $this->des[0]->disablePadding();\r
223                 $this->des[1]->disablePadding();\r
224                 $this->des[2]->disablePadding();\r
225 \r
226                 switch ($mode) {\r
227                     case CRYPT_DES_MODE_ECB:\r
228                     case CRYPT_DES_MODE_CBC:\r
229                         $this->mode = $mode;\r
230                         break;\r
231                     default:\r
232                         $this->mode = CRYPT_DES_MODE_CBC;\r
233                 }\r
234         }\r
235     }\r
236 \r
237     /**\r
238      * Sets the key.\r
239      *\r
240      * Keys can be of any length.  Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or\r
241      * 192-bit (eg. strlen($key) == 24) keys.  This function pads and truncates $key as appropriate.\r
242      *\r
243      * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.\r
244      *\r
245      * If the key is not explicitly set, it'll be assumed to be all zero's.\r
246      *\r
247      * @access public\r
248      * @param String $key\r
249      */\r
250     function setKey($key)\r
251     {\r
252         $length = strlen($key);\r
253         if ($length > 8) {\r
254             $key = str_pad($key, 24, chr(0));\r
255             // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:\r
256             // http://php.net/function.mcrypt-encrypt#47973\r
257             $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);\r
258         }\r
259         $this->key = $key;\r
260         switch (true) {\r
261             case CRYPT_DES_MODE == CRYPT_DES_MODE_INTERNAL:\r
262             case $this->mode == CRYPT_DES_MODE_3CBC:\r
263                 $this->des[0]->setKey(substr($key,  0, 8));\r
264                 $this->des[1]->setKey(substr($key,  8, 8));\r
265                 $this->des[2]->setKey(substr($key, 16, 8));\r
266         }\r
267     }\r
268 \r
269     /**\r
270      * Sets the initialization vector. (optional)\r
271      *\r
272      * SetIV is not required when CRYPT_DES_MODE_ECB is being used.  If not explictly set, it'll be assumed\r
273      * to be all zero's.\r
274      *\r
275      * @access public\r
276      * @param String $iv\r
277      */\r
278     function setIV($iv)\r
279     {\r
280         $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));\r
281         if ($this->mode == CRYPT_DES_MODE_3CBC) {\r
282             $this->des[0]->setIV($iv);\r
283             $this->des[1]->setIV($iv);\r
284             $this->des[2]->setIV($iv);\r
285         }\r
286     }\r
287 \r
288     /**\r
289      * Sets MCrypt parameters. (optional)\r
290      *\r
291      * If MCrypt is being used, empty strings will be used, unless otherwise specified.\r
292      *\r
293      * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open\r
294      * @access public\r
295      * @param optional Integer $algorithm_directory\r
296      * @param optional Integer $mode_directory\r
297      */\r
298     function setMCrypt($algorithm_directory = '', $mode_directory = '')\r
299     {\r
300         $this->mcrypt = array($algorithm_directory, $mode_directory);\r
301         if ( $this->mode == CRYPT_DES_MODE_3CBC ) {\r
302             $this->des[0]->setMCrypt($algorithm_directory, $mode_directory);\r
303             $this->des[1]->setMCrypt($algorithm_directory, $mode_directory);\r
304             $this->des[2]->setMCrypt($algorithm_directory, $mode_directory);\r
305         }\r
306     }\r
307 \r
308     /**\r
309      * Encrypts a message.\r
310      *\r
311      * @access public\r
312      * @param String $plaintext\r
313      */\r
314     function encrypt($plaintext)\r
315     {\r
316         $plaintext = $this->_pad($plaintext);\r
317 \r
318         // if the key is smaller then 8, do what we'd normally do\r
319         if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {\r
320             $ciphertext = $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($plaintext)));\r
321 \r
322             return $ciphertext;\r
323         }\r
324 \r
325         if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {\r
326             $td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);\r
327             mcrypt_generic_init($td, $this->key, $this->encryptIV);\r
328 \r
329             $ciphertext = mcrypt_generic($td, $plaintext);\r
330 \r
331             mcrypt_generic_deinit($td);\r
332             mcrypt_module_close($td);\r
333 \r
334             if ($this->continuousBuffer) {\r
335                 $this->encryptIV = substr($ciphertext, -8);\r
336             }\r
337 \r
338             return $ciphertext;\r
339         }\r
340 \r
341         if (strlen($this->key) <= 8) {\r
342             $this->des[0]->mode = $this->mode;\r
343 \r
344             return $this->des[0]->encrypt($plaintext);\r
345         }\r
346 \r
347         // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :\r
348         // "The data is padded with "\0" to make sure the length of the data is n * blocksize."\r
349         $plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));\r
350 \r
351         $ciphertext = '';\r
352         switch ($this->mode) {\r
353             case CRYPT_DES_MODE_ECB:\r
354                 for ($i = 0; $i < strlen($plaintext); $i+=8) {\r
355                     $block = substr($plaintext, $i, 8);\r
356                     $block = $this->des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
357                     $block = $this->des[1]->_processBlock($block, CRYPT_DES_DECRYPT);\r
358                     $block = $this->des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
359                     $ciphertext.= $block;\r
360                 }\r
361                 break;\r
362             case CRYPT_DES_MODE_CBC:\r
363                 $xor = $this->encryptIV;\r
364                 for ($i = 0; $i < strlen($plaintext); $i+=8) {\r
365                     $block = substr($plaintext, $i, 8) ^ $xor;\r
366                     $block = $this->des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
367                     $block = $this->des[1]->_processBlock($block, CRYPT_DES_DECRYPT);\r
368                     $block = $this->des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
369                     $xor = $block;\r
370                     $ciphertext.= $block;\r
371                 }\r
372                 if ($this->continuousBuffer) {\r
373                     $this->encryptIV = $xor;\r
374                 }\r
375         }\r
376 \r
377         return $ciphertext;\r
378     }\r
379 \r
380     /**\r
381      * Decrypts a message.\r
382      *\r
383      * @access public\r
384      * @param String $ciphertext\r
385      */\r
386     function decrypt($ciphertext)\r
387     {\r
388         if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {\r
389             $plaintext = $this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt($ciphertext)));\r
390 \r
391             return $this->_unpad($plaintext);\r
392         }\r
393 \r
394         // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :\r
395         // "The data is padded with "\0" to make sure the length of the data is n * blocksize."\r
396         $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));\r
397 \r
398         if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {\r
399             $td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);\r
400             mcrypt_generic_init($td, $this->key, $this->decryptIV);\r
401 \r
402             $plaintext = mdecrypt_generic($td, $ciphertext);\r
403 \r
404             mcrypt_generic_deinit($td);\r
405             mcrypt_module_close($td);\r
406 \r
407             if ($this->continuousBuffer) {\r
408                 $this->decryptIV = substr($ciphertext, -8);\r
409             }\r
410 \r
411             return $this->_unpad($plaintext);\r
412         }\r
413 \r
414         if (strlen($this->key) <= 8) {\r
415             $this->des[0]->mode = $this->mode;\r
416 \r
417             return $this->_unpad($this->des[0]->decrypt($plaintext));\r
418         }\r
419 \r
420         $plaintext = '';\r
421         switch ($this->mode) {\r
422             case CRYPT_DES_MODE_ECB:\r
423                 for ($i = 0; $i < strlen($ciphertext); $i+=8) {\r
424                     $block = substr($ciphertext, $i, 8);\r
425                     $block = $this->des[2]->_processBlock($block, CRYPT_DES_DECRYPT);\r
426                     $block = $this->des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
427                     $block = $this->des[0]->_processBlock($block, CRYPT_DES_DECRYPT);\r
428                     $plaintext.= $block;\r
429                 }\r
430                 break;\r
431             case CRYPT_DES_MODE_CBC:\r
432                 $xor = $this->decryptIV;\r
433                 for ($i = 0; $i < strlen($ciphertext); $i+=8) {\r
434                     $orig = $block = substr($ciphertext, $i, 8);\r
435                     $block = $this->des[2]->_processBlock($block, CRYPT_DES_DECRYPT);\r
436                     $block = $this->des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);\r
437                     $block = $this->des[0]->_processBlock($block, CRYPT_DES_DECRYPT);\r
438                     $plaintext.= $block ^ $xor;\r
439                     $xor = $orig;\r
440                 }\r
441                 if ($this->continuousBuffer) {\r
442                     $this->decryptIV = $xor;\r
443                 }\r
444         }\r
445 \r
446         return $this->_unpad($plaintext);\r
447     }\r
448 \r
449     /**\r
450      * Treat consecutive "packets" as if they are a continuous buffer.\r
451      *\r
452      * Say you have a 16-byte plaintext $plaintext.  Using the default behavior, the two following code snippets\r
453      * will yield different outputs:\r
454      *\r
455      * <code>\r
456      *    echo $des->encrypt(substr($plaintext, 0, 8));\r
457      *    echo $des->encrypt(substr($plaintext, 8, 8));\r
458      * </code>\r
459      * <code>\r
460      *    echo $des->encrypt($plaintext);\r
461      * </code>\r
462      *\r
463      * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates\r
464      * another, as demonstrated with the following:\r
465      *\r
466      * <code>\r
467      *    $des->encrypt(substr($plaintext, 0, 8));\r
468      *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));\r
469      * </code>\r
470      * <code>\r
471      *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));\r
472      * </code>\r
473      *\r
474      * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different\r
475      * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /\r
476      * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.\r
477      *\r
478      * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each\r
479      * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that\r
480      * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),\r
481      * however, they are also less intuitive and more likely to cause you problems.\r
482      *\r
483      * @see Crypt_TripleDES::disableContinuousBuffer()\r
484      * @access public\r
485      */\r
486     function enableContinuousBuffer()\r
487     {\r
488         $this->continuousBuffer = true;\r
489         if ($this->mode == CRYPT_DES_MODE_3CBC) {\r
490             $this->des[0]->enableContinuousBuffer();\r
491             $this->des[1]->enableContinuousBuffer();\r
492             $this->des[2]->enableContinuousBuffer();\r
493         }\r
494     }\r
495 \r
496     /**\r
497      * Treat consecutive packets as if they are a discontinuous buffer.\r
498      *\r
499      * The default behavior.\r
500      *\r
501      * @see Crypt_TripleDES::enableContinuousBuffer()\r
502      * @access public\r
503      */\r
504     function disableContinuousBuffer()\r
505     {\r
506         $this->continuousBuffer = false;\r
507         $this->encryptIV = $this->iv;\r
508         $this->decryptIV = $this->iv;\r
509 \r
510         if ($this->mode == CRYPT_DES_MODE_3CBC) {\r
511             $this->des[0]->disableContinuousBuffer();\r
512             $this->des[1]->disableContinuousBuffer();\r
513             $this->des[2]->disableContinuousBuffer();\r
514         }\r
515     }\r
516 \r
517     /**\r
518      * Pad "packets".\r
519      *\r
520      * DES works by encrypting eight bytes at a time.  If you ever need to encrypt or decrypt something that's not\r
521      * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.\r
522      *\r
523      * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH1,\r
524      * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping\r
525      * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is\r
526      * transmitted separately)\r
527      *\r
528      * @see Crypt_TripleDES::disablePadding()\r
529      * @access public\r
530      */\r
531     function enablePadding()\r
532     {\r
533         $this->padding = true;\r
534     }\r
535 \r
536     /**\r
537      * Do not pad packets.\r
538      *\r
539      * @see Crypt_TripleDES::enablePadding()\r
540      * @access public\r
541      */\r
542     function disablePadding()\r
543     {\r
544         $this->padding = false;\r
545     }\r
546 \r
547     /**\r
548      * Pads a string\r
549      *\r
550      * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).\r
551      * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)\r
552      *\r
553      * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless\r
554      * and padding will, hence forth, be enabled.\r
555      *\r
556      * @see Crypt_TripleDES::_unpad()\r
557      * @access private\r
558      */\r
559     function _pad($text)\r
560     {\r
561         $length = strlen($text);\r
562 \r
563         if (!$this->padding) {\r
564             if (($length & 7) == 0) {\r
565                 return $text;\r
566             } else {\r
567                 user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);\r
568                 $this->padding = true;\r
569             }\r
570         }\r
571 \r
572         $pad = 8 - ($length & 7);\r
573         return str_pad($text, $length + $pad, chr($pad));\r
574     }\r
575 \r
576     /**\r
577      * Unpads a string\r
578      *\r
579      * If padding is enabled and the reported padding length is invalid, padding will be, hence forth, disabled.\r
580      *\r
581      * @see Crypt_TripleDES::_pad()\r
582      * @access private\r
583      */\r
584     function _unpad($text)\r
585     {\r
586         if (!$this->padding) {\r
587             return $text;\r
588         }\r
589 \r
590         $length = ord($text[strlen($text) - 1]);\r
591 \r
592         if (!$length || $length > 8) {\r
593             user_error("The number of bytes reported as being padded ($length) is invalid (block size = 8)", E_USER_NOTICE);\r
594             $this->padding = false;\r
595             return $text;\r
596         }\r
597 \r
598         return substr($text, 0, -$length);\r
599     }\r
600 }\r
601 \r
602 // vim: ts=4:sw=4:et:\r
603 // vim6: fdl=1: