]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/OStatus/extlib/phpseclib/Crypt/Twofish.php
Latest phpseclib stuff and moved into its own dir.
[quix0rs-gnu-social.git] / plugins / OStatus / extlib / phpseclib / Crypt / Twofish.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4 /**
5  * Pure-PHP implementation of Twofish.
6  *
7  * Uses mcrypt, if available, and an internal implementation, otherwise.
8  *
9  * PHP versions 4 and 5
10  *
11  * Useful resources are as follows:
12  *
13  *  - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
14  *
15  * Here's a short example of how to use this library:
16  * <code>
17  * <?php
18  *    include('Crypt/Twofish.php');
19  *
20  *    $twofish = new Crypt_Twofish();
21  *
22  *    $twofish->setKey('12345678901234567890123456789012');
23  *
24  *    $plaintext = str_repeat('a', 1024);
25  *
26  *    echo $twofish->decrypt($twofish->encrypt($plaintext));
27  * ?>
28  * </code>
29  *
30  * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
31  * of this software and associated documentation files (the "Software"), to deal
32  * in the Software without restriction, including without limitation the rights
33  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
34  * copies of the Software, and to permit persons to whom the Software is
35  * furnished to do so, subject to the following conditions:
36  *
37  * The above copyright notice and this permission notice shall be included in
38  * all copies or substantial portions of the Software.
39  *
40  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
43  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
45  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
46  * THE SOFTWARE.
47  *
48  * @category   Crypt
49  * @package    Crypt_Twofish
50  * @author     Jim Wigginton <terrafrost@php.net>
51  * @author     Hans-Juergen Petrich <petrich@tronic-media.com>
52  * @copyright  MMVII Jim Wigginton
53  * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
54  * @version    1.0
55  * @link       http://phpseclib.sourceforge.net
56  */
57
58 /**
59  * Include Crypt_Base
60  *
61  * Base cipher class
62  */
63 if (!class_exists('Crypt_Base')) {
64     require_once('Base.php');
65 }
66
67 /**#@+
68  * @access public
69  * @see Crypt_Twofish::encrypt()
70  * @see Crypt_Twofish::decrypt()
71  */
72 /**
73  * Encrypt / decrypt using the Counter mode.
74  *
75  * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
76  *
77  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
78  */
79 define('CRYPT_TWOFISH_MODE_CTR', CRYPT_MODE_CTR);
80 /**
81  * Encrypt / decrypt using the Electronic Code Book mode.
82  *
83  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
84  */
85 define('CRYPT_TWOFISH_MODE_ECB', CRYPT_MODE_ECB);
86 /**
87  * Encrypt / decrypt using the Code Book Chaining mode.
88  *
89  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
90  */
91 define('CRYPT_TWOFISH_MODE_CBC', CRYPT_MODE_CBC);
92 /**
93  * Encrypt / decrypt using the Cipher Feedback mode.
94  *
95  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
96  */
97 define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
98 /**
99  * Encrypt / decrypt using the Cipher Feedback mode.
100  *
101  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
102  */
103 define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
104 /**#@-*/
105
106 /**#@+
107  * @access private
108  * @see Crypt_Twofish::Crypt_Twofish()
109  */
110 /**
111  * Toggles the internal implementation
112  */
113 define('CRYPT_TWOFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
114 /**
115  * Toggles the mcrypt implementation
116  */
117 define('CRYPT_TWOFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
118 /**#@-*/
119
120 /**
121  * Pure-PHP implementation of Twofish.
122  *
123  * @author  Jim Wigginton <terrafrost@php.net>
124  * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
125  * @version 1.0
126  * @access  public
127  * @package Crypt_Twofish
128  */
129 class Crypt_Twofish extends Crypt_Base {
130     /**
131      * The namespace used by the cipher for its constants.
132      *
133      * @see Crypt_Base::const_namespace
134      * @var String
135      * @access private
136      */
137     var $const_namespace = 'TWOFISH';
138
139     /**
140      * The mcrypt specific name of the cipher
141      *
142      * @see Crypt_Base::cipher_name_mcrypt
143      * @var String
144      * @access private
145      */
146     var $cipher_name_mcrypt = 'twofish';
147
148     /**
149      * Optimizing value while CFB-encrypting
150      *
151      * @see Crypt_Base::cfb_init_len
152      * @var Integer
153      * @access private
154      */
155     var $cfb_init_len = 800;
156
157     /**
158      * Q-Table
159      *
160      * @var Array
161      * @access private
162      */
163     var $q0 = array (
164         0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
165         0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
166         0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
167         0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
168         0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
169         0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
170         0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
171         0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
172         0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
173         0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
174         0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
175         0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
176         0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
177         0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
178         0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
179         0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
180         0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
181         0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
182         0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
183         0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
184         0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
185         0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
186         0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
187         0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
188         0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
189         0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
190         0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
191         0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
192         0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
193         0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
194         0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
195         0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
196     );
197
198     /**
199      * Q-Table
200      *
201      * @var Array
202      * @access private
203      */
204     var $q1 = array (
205         0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
206         0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
207         0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
208         0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
209         0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
210         0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
211         0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
212         0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
213         0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
214         0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
215         0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
216         0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
217         0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
218         0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
219         0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
220         0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
221         0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
222         0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
223         0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
224         0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
225         0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
226         0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
227         0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
228         0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
229         0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
230         0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
231         0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
232         0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
233         0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
234         0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
235         0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
236         0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
237     );
238
239     /**
240      * M-Table
241      *
242      * @var Array
243      * @access private
244      */
245     var $m0 = array (
246         0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
247         0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
248         0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
249         0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
250         0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
251         0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
252         0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
253         0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
254         0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
255         0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
256         0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
257         0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
258         0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
259         0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
260         0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
261         0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
262         0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
263         0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
264         0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
265         0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
266         0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
267         0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
268         0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
269         0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
270         0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
271         0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
272         0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
273         0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
274         0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
275         0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
276         0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
277         0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
278     );
279
280     /**
281      * M-Table
282      *
283      * @var Array
284      * @access private
285      */
286     var $m1 = array (
287         0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
288         0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
289         0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
290         0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
291         0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
292         0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
293         0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
294         0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
295         0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
296         0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
297         0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
298         0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
299         0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
300         0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
301         0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
302         0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
303         0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
304         0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
305         0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
306         0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
307         0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
308         0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
309         0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
310         0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
311         0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
312         0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
313         0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
314         0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
315         0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
316         0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
317         0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
318         0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
319     );
320
321     /**
322      * M-Table
323      *
324      * @var Array
325      * @access private
326      */
327     var $m2 = array (
328         0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
329         0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
330         0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
331         0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
332         0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
333         0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
334         0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
335         0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
336         0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
337         0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
338         0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
339         0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
340         0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
341         0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
342         0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
343         0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
344         0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
345         0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
346         0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
347         0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
348         0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
349         0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
350         0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
351         0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
352         0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
353         0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
354         0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
355         0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
356         0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
357         0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
358         0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
359         0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
360     );
361
362     /**
363      * M-Table
364      *
365      * @var Array
366      * @access private
367      */
368     var $m3 = array (
369         0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
370         0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
371         0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
372         0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
373         0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
374         0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
375         0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
376         0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
377         0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
378         0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
379         0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
380         0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
381         0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
382         0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
383         0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
384         0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
385         0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
386         0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
387         0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
388         0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
389         0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
390         0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
391         0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
392         0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
393         0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
394         0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
395         0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
396         0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
397         0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
398         0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
399         0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
400         0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
401     );
402
403     /**
404      * The Key Schedule Array
405      *
406      * @var Array
407      * @access private
408      */
409     var $K = array();
410
411     /**
412      * The Key depended S-Table 0
413      *
414      * @var Array
415      * @access private
416      */
417     var $S0 = array();
418
419     /**
420      * The Key depended S-Table 1
421      *
422      * @var Array
423      * @access private
424      */
425     var $S1 = array();
426
427     /**
428      * The Key depended S-Table 2
429      *
430      * @var Array
431      * @access private
432      */
433     var $S2 = array();
434
435     /**
436      * The Key depended S-Table 3
437      *
438      * @var Array
439      * @access private
440      */
441     var $S3 = array();
442
443     /**
444      * Holds the last used key
445      *
446      * @var Array
447      * @access private
448      */
449     var $kl;
450
451     /**
452      * Default Constructor.
453      *
454      * Determines whether or not the mcrypt extension should be used.
455      *
456      * $mode could be:
457      *
458      * - CRYPT_TWOFISH_MODE_ECB
459      *
460      * - CRYPT_TWOFISH_MODE_CBC
461      *
462      * - CRYPT_TWOFISH_MODE_CTR
463      *
464      * - CRYPT_TWOFISH_MODE_CFB
465      *
466      * - CRYPT_TWOFISH_MODE_OFB
467      *
468      * If not explictly set, CRYPT_TWOFISH_MODE_CBC will be used.
469      *
470      * @see Crypt_Base::Crypt_Base()
471      * @param optional Integer $mode
472      * @access public
473      */
474     function Crypt_Twofish($mode = CRYPT_TWOFISH_MODE_CBC)
475     {
476         parent::Crypt_Base($mode);
477     }
478
479     /**
480      * Sets the key.
481      *
482      * Keys can be of any length. Twofish, itself, requires the use of a key that's 128, 192 or 256-bits long.
483      * If the key is less than 256-bits we round the length up to the closest valid key length,
484      * padding $key with null bytes. If the key is more than 256-bits, we trim the excess bits.
485      *
486      * If the key is not explicitly set, it'll be assumed a 128 bits key to be all null bytes.
487      *
488      * @access public
489      * @see Crypt_Base::setKey()
490      * @param String $key
491      */
492     function setKey($key)
493     {
494         $keylength = strlen($key);
495         switch (true) {
496             case $keylength <= 16:
497                 $key = str_pad($key, 16, "\0");
498                 break;
499             case $keylength <= 24:
500                 $key = str_pad($key, 24, "\0");
501                 break;
502             case $keylength < 32:
503                 $key = str_pad($key, 32, "\0");
504                 break;
505             case $keylength > 32:
506                 $key = substr($key, 0, 32);
507         }
508         parent::setKey($key);
509     }
510
511     /**
512      * Setup the key (expansion)
513      *
514      * @see Crypt_Base::_setupKey()
515      * @access private
516      */
517     function _setupKey()
518     {
519         if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
520             // already expanded
521             return;
522         }
523         $this->kl = array('key' => $this->key);
524
525         /* Key expanding and generating the key-depended s-boxes */
526         $le_longs = unpack('V*', $this->key);
527         $key = unpack('C*', $this->key);
528         $m0 = $this->m0;
529         $m1 = $this->m1;
530         $m2 = $this->m2;
531         $m3 = $this->m3;
532         $q0 = $this->q0;
533         $q1 = $this->q1;
534
535         $K = $S0 = $S1 = $S2 = $S3 = array();
536
537         switch (strlen($this->key)) {
538             case 16:
539                 list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
540                 list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
541                 for ($i = 0, $j = 1; $i < 40; $i+= 2,$j+= 2) {
542                     $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
543                          $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
544                          $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
545                          $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
546                     $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
547                          $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
548                          $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
549                          $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
550                     $B = ($B << 8) | ($B >> 24 & 0xff);
551                     $K[] = $A+= $B;
552                     $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
553                 }
554                 for ($i = 0; $i < 256; ++$i) {
555                     $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
556                     $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
557                     $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
558                     $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
559                 }
560                 break;
561             case 24:
562                 list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
563                 list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
564                 list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
565                 for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
566                     $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
567                          $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
568                          $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
569                          $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
570                     $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
571                          $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
572                          $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
573                          $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
574                     $B = ($B << 8) | ($B >> 24 & 0xff);
575                     $K[] = $A+= $B;
576                     $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
577                 }
578                 for ($i = 0; $i < 256; ++$i) {
579                     $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
580                     $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
581                     $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
582                     $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
583                 }
584                 break;
585             default: // 32
586                 list ($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
587                 list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
588                 list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
589                 list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
590                 for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
591                     $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
592                          $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
593                          $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
594                          $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
595                     $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
596                          $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
597                          $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
598                          $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
599                     $B = ($B << 8) | ($B >> 24 & 0xff);
600                     $K[] = $A+= $B;
601                     $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
602                 }
603                 for ($i = 0; $i < 256; ++$i) {
604                     $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
605                     $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
606                     $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
607                     $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
608                 }
609         }
610
611         $this->K  = $K;
612         $this->S0 = $S0;
613         $this->S1 = $S1;
614         $this->S2 = $S2;
615         $this->S3 = $S3;
616     }
617
618     /**
619      * _mdsrem function using by the twofish cipher algorithm
620      *
621      * @access private
622      * @param String $A
623      * @param String $B
624      * @return Array
625      */
626     function _mdsrem($A, $B)
627     {
628         // No gain by unrolling this loop.
629         for ($i = 0; $i < 8; ++$i) {
630             // Get most significant coefficient.
631             $t = 0xff & ($B >> 24);
632
633             // Shift the others up.
634             $B = ($B << 8) | (0xff & ($A >> 24));
635             $A<<= 8;
636
637             $u = $t << 1;
638
639             // Subtract the modular polynomial on overflow.
640             if ($t & 0x80) {
641                 $u^= 0x14d;
642             }
643
644             // Remove t * (a * x^2 + 1).
645             $B ^= $t ^ ($u << 16);
646
647             // Form u = a*t + t/a = t*(a + 1/a).
648             $u^= 0x7fffffff & ($t >> 1);
649
650             // Add the modular polynomial on underflow.
651             if ($t & 0x01) $u^= 0xa6 ;
652
653             // Remove t * (a + 1/a) * (x^3 + x).
654             $B^= ($u << 24) | ($u << 8);
655         }
656
657         return array(
658             0xff & $B >> 24,
659             0xff & $B >> 16,
660             0xff & $B >>  8,
661             0xff & $B);
662     }
663
664     /**
665      * Encrypts a block
666      *
667      * @access private
668      * @param String $in
669      * @return String
670      */
671     function _encryptBlock($in)
672     {
673         $S0 = $this->S0;
674         $S1 = $this->S1;
675         $S2 = $this->S2;
676         $S3 = $this->S3;
677         $K  = $this->K;
678
679         $in = unpack("V4", $in);
680         $R0 = $K[0] ^ $in[1];
681         $R1 = $K[1] ^ $in[2];
682         $R2 = $K[2] ^ $in[3];
683         $R3 = $K[3] ^ $in[4];
684
685         $ki = 7;
686         while ($ki < 39) {
687             $t0 = $S0[ $R0        & 0xff] ^
688                   $S1[($R0 >>  8) & 0xff] ^
689                   $S2[($R0 >> 16) & 0xff] ^
690                   $S3[($R0 >> 24) & 0xff];
691             $t1 = $S0[($R1 >> 24) & 0xff] ^
692                   $S1[ $R1        & 0xff] ^
693                   $S2[($R1 >>  8) & 0xff] ^
694                   $S3[($R1 >> 16) & 0xff];
695             $R2^= $t0 + $t1 + $K[++$ki];
696             $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
697             $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
698
699             $t0 = $S0[ $R2        & 0xff] ^
700                   $S1[($R2 >>  8) & 0xff] ^
701                   $S2[($R2 >> 16) & 0xff] ^
702                   $S3[($R2 >> 24) & 0xff];
703             $t1 = $S0[($R3 >> 24) & 0xff] ^
704                   $S1[ $R3        & 0xff] ^
705                   $S2[($R3 >>  8) & 0xff] ^
706                   $S3[($R3 >> 16) & 0xff];
707             $R0^= ($t0 + $t1 + $K[++$ki]);
708             $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
709             $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
710         }
711
712         return pack("V4", $K[4] ^ $R2,
713                           $K[5] ^ $R3,
714                           $K[6] ^ $R0,
715                           $K[7] ^ $R1);
716     }
717
718     /**
719      * Decrypts a block
720      *
721      * @access private
722      * @param String $in
723      * @return String
724      */
725     function _decryptBlock($in)
726     {
727         $S0 = $this->S0;
728         $S1 = $this->S1;
729         $S2 = $this->S2;
730         $S3 = $this->S3;
731         $K  = $this->K;
732
733         $in = unpack("V4", $in);
734         $R0 = $K[4] ^ $in[1];
735         $R1 = $K[5] ^ $in[2];
736         $R2 = $K[6] ^ $in[3];
737         $R3 = $K[7] ^ $in[4];
738
739         $ki = 40;
740         while ($ki > 8) {
741             $t0 = $S0[$R0       & 0xff] ^
742                   $S1[$R0 >>  8 & 0xff] ^
743                   $S2[$R0 >> 16 & 0xff] ^
744                   $S3[$R0 >> 24 & 0xff];
745             $t1 = $S0[$R1 >> 24 & 0xff] ^
746                   $S1[$R1       & 0xff] ^
747                   $S2[$R1 >>  8 & 0xff] ^
748                   $S3[$R1 >> 16 & 0xff];
749             $R3^= $t0 + ($t1 << 1) + $K[--$ki];
750             $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
751             $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
752
753             $t0 = $S0[$R2       & 0xff] ^
754                   $S1[$R2 >>  8 & 0xff] ^
755                   $S2[$R2 >> 16 & 0xff] ^
756                   $S3[$R2 >> 24 & 0xff];
757             $t1 = $S0[$R3 >> 24 & 0xff] ^
758                   $S1[$R3       & 0xff] ^
759                   $S2[$R3 >>  8 & 0xff] ^
760                   $S3[$R3 >> 16 & 0xff];
761             $R1^= $t0 + ($t1 << 1) + $K[--$ki];
762             $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
763             $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
764         }
765
766         return pack("V4", $K[0] ^ $R2,
767                           $K[1] ^ $R3,
768                           $K[2] ^ $R0,
769                           $K[3] ^ $R1);
770     }
771
772     /**
773      * Setup the performance-optimized function for de/encrypt()
774      *
775      * @see Crypt_Base::_setupInlineCrypt()
776      * @access private
777      */
778     function _setupInlineCrypt()
779     {
780         $lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
781
782         // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
783         $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
784
785         switch (true) {
786             case $gen_hi_opt_code:
787                 $code_hash = md5(str_pad("Crypt_Twofish, {$this->mode}, ", 32, "\0") . $this->key);
788                 break;
789             default:
790                 $code_hash = "Crypt_Twofish, {$this->mode}";
791         }
792
793         if (!isset($lambda_functions[$code_hash])) {
794             switch (true) {
795                 case $gen_hi_opt_code:
796                     $K = $this->K;
797
798                     $init_crypt = '
799                         static $S0, $S1, $S2, $S3;
800                         if (!$S0) {
801                             for ($i = 0; $i < 256; ++$i) {
802                                 $S0[] = (int)$self->S0[$i];
803                                 $S1[] = (int)$self->S1[$i];
804                                 $S2[] = (int)$self->S2[$i];
805                                 $S3[] = (int)$self->S3[$i];
806                             }
807                         }
808                     ';
809                     break;
810                 default:
811                     $K   = array();
812                     for ($i = 0; $i < 40; ++$i) {
813                         $K[] = '$K_' . $i;
814                     }
815
816                     $init_crypt = '
817                         $S0 = $self->S0;
818                         $S1 = $self->S1;
819                         $S2 = $self->S2;
820                         $S3 = $self->S3;
821                         list(' . implode(',', $K) . ') = $self->K;
822                     ';
823             }
824
825             // Generating encrypt code:
826             $encrypt_block = '
827                 $in = unpack("V4", $in);
828                 $R0 = '.$K[0].' ^ $in[1];
829                 $R1 = '.$K[1].' ^ $in[2];
830                 $R2 = '.$K[2].' ^ $in[3];
831                 $R3 = '.$K[3].' ^ $in[4];
832             ';
833             for ($ki = 7, $i = 0; $i < 8; ++$i) {
834                 $encrypt_block.= '
835                     $t0 = $S0[ $R0        & 0xff] ^
836                           $S1[($R0 >>  8) & 0xff] ^
837                           $S2[($R0 >> 16) & 0xff] ^
838                           $S3[($R0 >> 24) & 0xff];
839                     $t1 = $S0[($R1 >> 24) & 0xff] ^
840                           $S1[ $R1        & 0xff] ^
841                           $S2[($R1 >>  8) & 0xff] ^
842                           $S3[($R1 >> 16) & 0xff];
843                     $R2^= ($t0 + $t1 + '.$K[++$ki].');
844                     $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
845                     $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
846
847                     $t0 = $S0[ $R2        & 0xff] ^
848                           $S1[($R2 >>  8) & 0xff] ^
849                           $S2[($R2 >> 16) & 0xff] ^
850                           $S3[($R2 >> 24) & 0xff];
851                     $t1 = $S0[($R3 >> 24) & 0xff] ^
852                           $S1[ $R3        & 0xff] ^
853                           $S2[($R3 >>  8) & 0xff] ^
854                           $S3[($R3 >> 16) & 0xff];
855                     $R0^= ($t0 + $t1 + '.$K[++$ki].');
856                     $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
857                     $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
858                 ';
859             }
860             $encrypt_block.= '
861                 $in = pack("V4", '.$K[4].' ^ $R2,
862                                  '.$K[5].' ^ $R3,
863                                  '.$K[6].' ^ $R0,
864                                  '.$K[7].' ^ $R1);
865             ';
866
867             // Generating decrypt code:
868             $decrypt_block = '
869                 $in = unpack("V4", $in);
870                 $R0 = '.$K[4].' ^ $in[1];
871                 $R1 = '.$K[5].' ^ $in[2];
872                 $R2 = '.$K[6].' ^ $in[3];
873                 $R3 = '.$K[7].' ^ $in[4];
874             ';
875             for ($ki = 40, $i = 0; $i < 8; ++$i) {
876                 $decrypt_block.= '
877                     $t0 = $S0[$R0       & 0xff] ^
878                           $S1[$R0 >>  8 & 0xff] ^
879                           $S2[$R0 >> 16 & 0xff] ^
880                           $S3[$R0 >> 24 & 0xff];
881                     $t1 = $S0[$R1 >> 24 & 0xff] ^
882                           $S1[$R1       & 0xff] ^
883                           $S2[$R1 >>  8 & 0xff] ^
884                           $S3[$R1 >> 16 & 0xff];
885                     $R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
886                     $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
887                     $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
888
889                     $t0 = $S0[$R2       & 0xff] ^
890                           $S1[$R2 >>  8 & 0xff] ^
891                           $S2[$R2 >> 16 & 0xff] ^
892                           $S3[$R2 >> 24 & 0xff];
893                     $t1 = $S0[$R3 >> 24 & 0xff] ^
894                           $S1[$R3       & 0xff] ^
895                           $S2[$R3 >>  8 & 0xff] ^
896                           $S3[$R3 >> 16 & 0xff];
897                     $R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
898                     $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
899                     $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
900                 ';
901             }
902             $decrypt_block.= '
903                 $in = pack("V4", '.$K[0].' ^ $R2,
904                                  '.$K[1].' ^ $R3,
905                                  '.$K[2].' ^ $R0,
906                                  '.$K[3].' ^ $R1);
907             ';
908
909             $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
910                 array(
911                    'init_crypt'    => $init_crypt,
912                    'init_encrypt'  => '',
913                    'init_decrypt'  => '',
914                    'encrypt_block' => $encrypt_block,
915                    'decrypt_block' => $decrypt_block
916                 )
917             );
918         }
919         $this->inline_crypt = $lambda_functions[$code_hash];
920     }
921 }
922
923 // vim: ts=4:sw=4:et:
924 // vim6: fdl=1: