1<?php
2
3/**
4 * Pure-PHP implementation of DES.
5 *
6 * Uses mcrypt, if available, and an internal implementation, otherwise.
7 *
8 * PHP version 5
9 *
10 * Useful resources are as follows:
11 *
12 *  - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
13 *  - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
14 *  - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
15 *
16 * Here's a short example of how to use this library:
17 * <code>
18 * <?php
19 *    include 'vendor/autoload.php';
20 *
21 *    $des = new \phpseclib\Crypt\DES();
22 *
23 *    $des->setKey('abcdefgh');
24 *
25 *    $size = 10 * 1024;
26 *    $plaintext = '';
27 *    for ($i = 0; $i < $size; $i++) {
28 *        $plaintext.= 'a';
29 *    }
30 *
31 *    echo $des->decrypt($des->encrypt($plaintext));
32 * ?>
33 * </code>
34 *
35 * @category  Crypt
36 * @package   DES
37 * @author    Jim Wigginton <terrafrost@php.net>
38 * @copyright 2007 Jim Wigginton
39 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
40 * @link      http://phpseclib.sourceforge.net
41 */
42
43namespace phpseclib\Crypt;
44
45/**
46 * Pure-PHP implementation of DES.
47 *
48 * @package DES
49 * @author  Jim Wigginton <terrafrost@php.net>
50 * @access  public
51 */
52class DES extends Base
53{
54    /**#@+
55     * @access private
56     * @see \phpseclib\Crypt\DES::_setupKey()
57     * @see \phpseclib\Crypt\DES::_processBlock()
58     */
59    /**
60     * Contains $keys[self::ENCRYPT]
61     */
62    const ENCRYPT = 0;
63    /**
64     * Contains $keys[self::DECRYPT]
65     */
66    const DECRYPT = 1;
67    /**#@-*/
68
69    /**
70     * Block Length of the cipher
71     *
72     * @see \phpseclib\Crypt\Base::block_size
73     * @var int
74     * @access private
75     */
76    var $block_size = 8;
77
78    /**
79     * Key Length (in bytes)
80     *
81     * @see \phpseclib\Crypt\Base::setKeyLength()
82     * @var int
83     * @access private
84     */
85    var $key_length = 8;
86
87    /**
88     * The mcrypt specific name of the cipher
89     *
90     * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
91     * @var string
92     * @access private
93     */
94    var $cipher_name_mcrypt = 'des';
95
96    /**
97     * The OpenSSL names of the cipher / modes
98     *
99     * @see \phpseclib\Crypt\Base::openssl_mode_names
100     * @var array
101     * @access private
102     */
103    var $openssl_mode_names = array(
104        self::MODE_ECB => 'des-ecb',
105        self::MODE_CBC => 'des-cbc',
106        self::MODE_CFB => 'des-cfb',
107        self::MODE_OFB => 'des-ofb'
108        // self::MODE_CTR is undefined for DES
109    );
110
111    /**
112     * Optimizing value while CFB-encrypting
113     *
114     * @see \phpseclib\Crypt\Base::cfb_init_len
115     * @var int
116     * @access private
117     */
118    var $cfb_init_len = 500;
119
120    /**
121     * Switch for DES/3DES encryption
122     *
123     * Used only if $engine == self::ENGINE_INTERNAL
124     *
125     * @see self::_setupKey()
126     * @see self::_processBlock()
127     * @var int
128     * @access private
129     */
130    var $des_rounds = 1;
131
132    /**
133     * max possible size of $key
134     *
135     * @see self::setKey()
136     * @var string
137     * @access private
138     */
139    var $key_length_max = 8;
140
141    /**
142     * The Key Schedule
143     *
144     * @see self::_setupKey()
145     * @var array
146     * @access private
147     */
148    var $keys;
149
150    /**
151     * Shuffle table.
152     *
153     * For each byte value index, the entry holds an 8-byte string
154     * with each byte containing all bits in the same state as the
155     * corresponding bit in the index value.
156     *
157     * @see self::_processBlock()
158     * @see self::_setupKey()
159     * @var array
160     * @access private
161     */
162    var $shuffle = array(
163        "\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xFF",
164        "\x00\x00\x00\x00\x00\x00\xFF\x00", "\x00\x00\x00\x00\x00\x00\xFF\xFF",
165        "\x00\x00\x00\x00\x00\xFF\x00\x00", "\x00\x00\x00\x00\x00\xFF\x00\xFF",
166        "\x00\x00\x00\x00\x00\xFF\xFF\x00", "\x00\x00\x00\x00\x00\xFF\xFF\xFF",
167        "\x00\x00\x00\x00\xFF\x00\x00\x00", "\x00\x00\x00\x00\xFF\x00\x00\xFF",
168        "\x00\x00\x00\x00\xFF\x00\xFF\x00", "\x00\x00\x00\x00\xFF\x00\xFF\xFF",
169        "\x00\x00\x00\x00\xFF\xFF\x00\x00", "\x00\x00\x00\x00\xFF\xFF\x00\xFF",
170        "\x00\x00\x00\x00\xFF\xFF\xFF\x00", "\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
171        "\x00\x00\x00\xFF\x00\x00\x00\x00", "\x00\x00\x00\xFF\x00\x00\x00\xFF",
172        "\x00\x00\x00\xFF\x00\x00\xFF\x00", "\x00\x00\x00\xFF\x00\x00\xFF\xFF",
173        "\x00\x00\x00\xFF\x00\xFF\x00\x00", "\x00\x00\x00\xFF\x00\xFF\x00\xFF",
174        "\x00\x00\x00\xFF\x00\xFF\xFF\x00", "\x00\x00\x00\xFF\x00\xFF\xFF\xFF",
175        "\x00\x00\x00\xFF\xFF\x00\x00\x00", "\x00\x00\x00\xFF\xFF\x00\x00\xFF",
176        "\x00\x00\x00\xFF\xFF\x00\xFF\x00", "\x00\x00\x00\xFF\xFF\x00\xFF\xFF",
177        "\x00\x00\x00\xFF\xFF\xFF\x00\x00", "\x00\x00\x00\xFF\xFF\xFF\x00\xFF",
178        "\x00\x00\x00\xFF\xFF\xFF\xFF\x00", "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF",
179        "\x00\x00\xFF\x00\x00\x00\x00\x00", "\x00\x00\xFF\x00\x00\x00\x00\xFF",
180        "\x00\x00\xFF\x00\x00\x00\xFF\x00", "\x00\x00\xFF\x00\x00\x00\xFF\xFF",
181        "\x00\x00\xFF\x00\x00\xFF\x00\x00", "\x00\x00\xFF\x00\x00\xFF\x00\xFF",
182        "\x00\x00\xFF\x00\x00\xFF\xFF\x00", "\x00\x00\xFF\x00\x00\xFF\xFF\xFF",
183        "\x00\x00\xFF\x00\xFF\x00\x00\x00", "\x00\x00\xFF\x00\xFF\x00\x00\xFF",
184        "\x00\x00\xFF\x00\xFF\x00\xFF\x00", "\x00\x00\xFF\x00\xFF\x00\xFF\xFF",
185        "\x00\x00\xFF\x00\xFF\xFF\x00\x00", "\x00\x00\xFF\x00\xFF\xFF\x00\xFF",
186        "\x00\x00\xFF\x00\xFF\xFF\xFF\x00", "\x00\x00\xFF\x00\xFF\xFF\xFF\xFF",
187        "\x00\x00\xFF\xFF\x00\x00\x00\x00", "\x00\x00\xFF\xFF\x00\x00\x00\xFF",
188        "\x00\x00\xFF\xFF\x00\x00\xFF\x00", "\x00\x00\xFF\xFF\x00\x00\xFF\xFF",
189        "\x00\x00\xFF\xFF\x00\xFF\x00\x00", "\x00\x00\xFF\xFF\x00\xFF\x00\xFF",
190        "\x00\x00\xFF\xFF\x00\xFF\xFF\x00", "\x00\x00\xFF\xFF\x00\xFF\xFF\xFF",
191        "\x00\x00\xFF\xFF\xFF\x00\x00\x00", "\x00\x00\xFF\xFF\xFF\x00\x00\xFF",
192        "\x00\x00\xFF\xFF\xFF\x00\xFF\x00", "\x00\x00\xFF\xFF\xFF\x00\xFF\xFF",
193        "\x00\x00\xFF\xFF\xFF\xFF\x00\x00", "\x00\x00\xFF\xFF\xFF\xFF\x00\xFF",
194        "\x00\x00\xFF\xFF\xFF\xFF\xFF\x00", "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
195        "\x00\xFF\x00\x00\x00\x00\x00\x00", "\x00\xFF\x00\x00\x00\x00\x00\xFF",
196        "\x00\xFF\x00\x00\x00\x00\xFF\x00", "\x00\xFF\x00\x00\x00\x00\xFF\xFF",
197        "\x00\xFF\x00\x00\x00\xFF\x00\x00", "\x00\xFF\x00\x00\x00\xFF\x00\xFF",
198        "\x00\xFF\x00\x00\x00\xFF\xFF\x00", "\x00\xFF\x00\x00\x00\xFF\xFF\xFF",
199        "\x00\xFF\x00\x00\xFF\x00\x00\x00", "\x00\xFF\x00\x00\xFF\x00\x00\xFF",
200        "\x00\xFF\x00\x00\xFF\x00\xFF\x00", "\x00\xFF\x00\x00\xFF\x00\xFF\xFF",
201        "\x00\xFF\x00\x00\xFF\xFF\x00\x00", "\x00\xFF\x00\x00\xFF\xFF\x00\xFF",
202        "\x00\xFF\x00\x00\xFF\xFF\xFF\x00", "\x00\xFF\x00\x00\xFF\xFF\xFF\xFF",
203        "\x00\xFF\x00\xFF\x00\x00\x00\x00", "\x00\xFF\x00\xFF\x00\x00\x00\xFF",
204        "\x00\xFF\x00\xFF\x00\x00\xFF\x00", "\x00\xFF\x00\xFF\x00\x00\xFF\xFF",
205        "\x00\xFF\x00\xFF\x00\xFF\x00\x00", "\x00\xFF\x00\xFF\x00\xFF\x00\xFF",
206        "\x00\xFF\x00\xFF\x00\xFF\xFF\x00", "\x00\xFF\x00\xFF\x00\xFF\xFF\xFF",
207        "\x00\xFF\x00\xFF\xFF\x00\x00\x00", "\x00\xFF\x00\xFF\xFF\x00\x00\xFF",
208        "\x00\xFF\x00\xFF\xFF\x00\xFF\x00", "\x00\xFF\x00\xFF\xFF\x00\xFF\xFF",
209        "\x00\xFF\x00\xFF\xFF\xFF\x00\x00", "\x00\xFF\x00\xFF\xFF\xFF\x00\xFF",
210        "\x00\xFF\x00\xFF\xFF\xFF\xFF\x00", "\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF",
211        "\x00\xFF\xFF\x00\x00\x00\x00\x00", "\x00\xFF\xFF\x00\x00\x00\x00\xFF",
212        "\x00\xFF\xFF\x00\x00\x00\xFF\x00", "\x00\xFF\xFF\x00\x00\x00\xFF\xFF",
213        "\x00\xFF\xFF\x00\x00\xFF\x00\x00", "\x00\xFF\xFF\x00\x00\xFF\x00\xFF",
214        "\x00\xFF\xFF\x00\x00\xFF\xFF\x00", "\x00\xFF\xFF\x00\x00\xFF\xFF\xFF",
215        "\x00\xFF\xFF\x00\xFF\x00\x00\x00", "\x00\xFF\xFF\x00\xFF\x00\x00\xFF",
216        "\x00\xFF\xFF\x00\xFF\x00\xFF\x00", "\x00\xFF\xFF\x00\xFF\x00\xFF\xFF",
217        "\x00\xFF\xFF\x00\xFF\xFF\x00\x00", "\x00\xFF\xFF\x00\xFF\xFF\x00\xFF",
218        "\x00\xFF\xFF\x00\xFF\xFF\xFF\x00", "\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF",
219        "\x00\xFF\xFF\xFF\x00\x00\x00\x00", "\x00\xFF\xFF\xFF\x00\x00\x00\xFF",
220        "\x00\xFF\xFF\xFF\x00\x00\xFF\x00", "\x00\xFF\xFF\xFF\x00\x00\xFF\xFF",
221        "\x00\xFF\xFF\xFF\x00\xFF\x00\x00", "\x00\xFF\xFF\xFF\x00\xFF\x00\xFF",
222        "\x00\xFF\xFF\xFF\x00\xFF\xFF\x00", "\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF",
223        "\x00\xFF\xFF\xFF\xFF\x00\x00\x00", "\x00\xFF\xFF\xFF\xFF\x00\x00\xFF",
224        "\x00\xFF\xFF\xFF\xFF\x00\xFF\x00", "\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF",
225        "\x00\xFF\xFF\xFF\xFF\xFF\x00\x00", "\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF",
226        "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
227        "\xFF\x00\x00\x00\x00\x00\x00\x00", "\xFF\x00\x00\x00\x00\x00\x00\xFF",
228        "\xFF\x00\x00\x00\x00\x00\xFF\x00", "\xFF\x00\x00\x00\x00\x00\xFF\xFF",
229        "\xFF\x00\x00\x00\x00\xFF\x00\x00", "\xFF\x00\x00\x00\x00\xFF\x00\xFF",
230        "\xFF\x00\x00\x00\x00\xFF\xFF\x00", "\xFF\x00\x00\x00\x00\xFF\xFF\xFF",
231        "\xFF\x00\x00\x00\xFF\x00\x00\x00", "\xFF\x00\x00\x00\xFF\x00\x00\xFF",
232        "\xFF\x00\x00\x00\xFF\x00\xFF\x00", "\xFF\x00\x00\x00\xFF\x00\xFF\xFF",
233        "\xFF\x00\x00\x00\xFF\xFF\x00\x00", "\xFF\x00\x00\x00\xFF\xFF\x00\xFF",
234        "\xFF\x00\x00\x00\xFF\xFF\xFF\x00", "\xFF\x00\x00\x00\xFF\xFF\xFF\xFF",
235        "\xFF\x00\x00\xFF\x00\x00\x00\x00", "\xFF\x00\x00\xFF\x00\x00\x00\xFF",
236        "\xFF\x00\x00\xFF\x00\x00\xFF\x00", "\xFF\x00\x00\xFF\x00\x00\xFF\xFF",
237        "\xFF\x00\x00\xFF\x00\xFF\x00\x00", "\xFF\x00\x00\xFF\x00\xFF\x00\xFF",
238        "\xFF\x00\x00\xFF\x00\xFF\xFF\x00", "\xFF\x00\x00\xFF\x00\xFF\xFF\xFF",
239        "\xFF\x00\x00\xFF\xFF\x00\x00\x00", "\xFF\x00\x00\xFF\xFF\x00\x00\xFF",
240        "\xFF\x00\x00\xFF\xFF\x00\xFF\x00", "\xFF\x00\x00\xFF\xFF\x00\xFF\xFF",
241        "\xFF\x00\x00\xFF\xFF\xFF\x00\x00", "\xFF\x00\x00\xFF\xFF\xFF\x00\xFF",
242        "\xFF\x00\x00\xFF\xFF\xFF\xFF\x00", "\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF",
243        "\xFF\x00\xFF\x00\x00\x00\x00\x00", "\xFF\x00\xFF\x00\x00\x00\x00\xFF",
244        "\xFF\x00\xFF\x00\x00\x00\xFF\x00", "\xFF\x00\xFF\x00\x00\x00\xFF\xFF",
245        "\xFF\x00\xFF\x00\x00\xFF\x00\x00", "\xFF\x00\xFF\x00\x00\xFF\x00\xFF",
246        "\xFF\x00\xFF\x00\x00\xFF\xFF\x00", "\xFF\x00\xFF\x00\x00\xFF\xFF\xFF",
247        "\xFF\x00\xFF\x00\xFF\x00\x00\x00", "\xFF\x00\xFF\x00\xFF\x00\x00\xFF",
248        "\xFF\x00\xFF\x00\xFF\x00\xFF\x00", "\xFF\x00\xFF\x00\xFF\x00\xFF\xFF",
249        "\xFF\x00\xFF\x00\xFF\xFF\x00\x00", "\xFF\x00\xFF\x00\xFF\xFF\x00\xFF",
250        "\xFF\x00\xFF\x00\xFF\xFF\xFF\x00", "\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF",
251        "\xFF\x00\xFF\xFF\x00\x00\x00\x00", "\xFF\x00\xFF\xFF\x00\x00\x00\xFF",
252        "\xFF\x00\xFF\xFF\x00\x00\xFF\x00", "\xFF\x00\xFF\xFF\x00\x00\xFF\xFF",
253        "\xFF\x00\xFF\xFF\x00\xFF\x00\x00", "\xFF\x00\xFF\xFF\x00\xFF\x00\xFF",
254        "\xFF\x00\xFF\xFF\x00\xFF\xFF\x00", "\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF",
255        "\xFF\x00\xFF\xFF\xFF\x00\x00\x00", "\xFF\x00\xFF\xFF\xFF\x00\x00\xFF",
256        "\xFF\x00\xFF\xFF\xFF\x00\xFF\x00", "\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF",
257        "\xFF\x00\xFF\xFF\xFF\xFF\x00\x00", "\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF",
258        "\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF",
259        "\xFF\xFF\x00\x00\x00\x00\x00\x00", "\xFF\xFF\x00\x00\x00\x00\x00\xFF",
260        "\xFF\xFF\x00\x00\x00\x00\xFF\x00", "\xFF\xFF\x00\x00\x00\x00\xFF\xFF",
261        "\xFF\xFF\x00\x00\x00\xFF\x00\x00", "\xFF\xFF\x00\x00\x00\xFF\x00\xFF",
262        "\xFF\xFF\x00\x00\x00\xFF\xFF\x00", "\xFF\xFF\x00\x00\x00\xFF\xFF\xFF",
263        "\xFF\xFF\x00\x00\xFF\x00\x00\x00", "\xFF\xFF\x00\x00\xFF\x00\x00\xFF",
264        "\xFF\xFF\x00\x00\xFF\x00\xFF\x00", "\xFF\xFF\x00\x00\xFF\x00\xFF\xFF",
265        "\xFF\xFF\x00\x00\xFF\xFF\x00\x00", "\xFF\xFF\x00\x00\xFF\xFF\x00\xFF",
266        "\xFF\xFF\x00\x00\xFF\xFF\xFF\x00", "\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF",
267        "\xFF\xFF\x00\xFF\x00\x00\x00\x00", "\xFF\xFF\x00\xFF\x00\x00\x00\xFF",
268        "\xFF\xFF\x00\xFF\x00\x00\xFF\x00", "\xFF\xFF\x00\xFF\x00\x00\xFF\xFF",
269        "\xFF\xFF\x00\xFF\x00\xFF\x00\x00", "\xFF\xFF\x00\xFF\x00\xFF\x00\xFF",
270        "\xFF\xFF\x00\xFF\x00\xFF\xFF\x00", "\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF",
271        "\xFF\xFF\x00\xFF\xFF\x00\x00\x00", "\xFF\xFF\x00\xFF\xFF\x00\x00\xFF",
272        "\xFF\xFF\x00\xFF\xFF\x00\xFF\x00", "\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF",
273        "\xFF\xFF\x00\xFF\xFF\xFF\x00\x00", "\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF",
274        "\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF",
275        "\xFF\xFF\xFF\x00\x00\x00\x00\x00", "\xFF\xFF\xFF\x00\x00\x00\x00\xFF",
276        "\xFF\xFF\xFF\x00\x00\x00\xFF\x00", "\xFF\xFF\xFF\x00\x00\x00\xFF\xFF",
277        "\xFF\xFF\xFF\x00\x00\xFF\x00\x00", "\xFF\xFF\xFF\x00\x00\xFF\x00\xFF",
278        "\xFF\xFF\xFF\x00\x00\xFF\xFF\x00", "\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF",
279        "\xFF\xFF\xFF\x00\xFF\x00\x00\x00", "\xFF\xFF\xFF\x00\xFF\x00\x00\xFF",
280        "\xFF\xFF\xFF\x00\xFF\x00\xFF\x00", "\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF",
281        "\xFF\xFF\xFF\x00\xFF\xFF\x00\x00", "\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF",
282        "\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF",
283        "\xFF\xFF\xFF\xFF\x00\x00\x00\x00", "\xFF\xFF\xFF\xFF\x00\x00\x00\xFF",
284        "\xFF\xFF\xFF\xFF\x00\x00\xFF\x00", "\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF",
285        "\xFF\xFF\xFF\xFF\x00\xFF\x00\x00", "\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF",
286        "\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF",
287        "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", "\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF",
288        "\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF",
289        "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF",
290        "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
291    );
292
293    /**
294     * IP mapping helper table.
295     *
296     * Indexing this table with each source byte performs the initial bit permutation.
297     *
298     * @var array
299     * @access private
300     */
301    var $ipmap = array(
302        0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x21, 0x31,
303        0x02, 0x12, 0x03, 0x13, 0x22, 0x32, 0x23, 0x33,
304        0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71,
305        0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73,
306        0x04, 0x14, 0x05, 0x15, 0x24, 0x34, 0x25, 0x35,
307        0x06, 0x16, 0x07, 0x17, 0x26, 0x36, 0x27, 0x37,
308        0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75,
309        0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77,
310        0x80, 0x90, 0x81, 0x91, 0xA0, 0xB0, 0xA1, 0xB1,
311        0x82, 0x92, 0x83, 0x93, 0xA2, 0xB2, 0xA3, 0xB3,
312        0xC0, 0xD0, 0xC1, 0xD1, 0xE0, 0xF0, 0xE1, 0xF1,
313        0xC2, 0xD2, 0xC3, 0xD3, 0xE2, 0xF2, 0xE3, 0xF3,
314        0x84, 0x94, 0x85, 0x95, 0xA4, 0xB4, 0xA5, 0xB5,
315        0x86, 0x96, 0x87, 0x97, 0xA6, 0xB6, 0xA7, 0xB7,
316        0xC4, 0xD4, 0xC5, 0xD5, 0xE4, 0xF4, 0xE5, 0xF5,
317        0xC6, 0xD6, 0xC7, 0xD7, 0xE6, 0xF6, 0xE7, 0xF7,
318        0x08, 0x18, 0x09, 0x19, 0x28, 0x38, 0x29, 0x39,
319        0x0A, 0x1A, 0x0B, 0x1B, 0x2A, 0x3A, 0x2B, 0x3B,
320        0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79,
321        0x4A, 0x5A, 0x4B, 0x5B, 0x6A, 0x7A, 0x6B, 0x7B,
322        0x0C, 0x1C, 0x0D, 0x1D, 0x2C, 0x3C, 0x2D, 0x3D,
323        0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
324        0x4C, 0x5C, 0x4D, 0x5D, 0x6C, 0x7C, 0x6D, 0x7D,
325        0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
326        0x88, 0x98, 0x89, 0x99, 0xA8, 0xB8, 0xA9, 0xB9,
327        0x8A, 0x9A, 0x8B, 0x9B, 0xAA, 0xBA, 0xAB, 0xBB,
328        0xC8, 0xD8, 0xC9, 0xD9, 0xE8, 0xF8, 0xE9, 0xF9,
329        0xCA, 0xDA, 0xCB, 0xDB, 0xEA, 0xFA, 0xEB, 0xFB,
330        0x8C, 0x9C, 0x8D, 0x9D, 0xAC, 0xBC, 0xAD, 0xBD,
331        0x8E, 0x9E, 0x8F, 0x9F, 0xAE, 0xBE, 0xAF, 0xBF,
332        0xCC, 0xDC, 0xCD, 0xDD, 0xEC, 0xFC, 0xED, 0xFD,
333        0xCE, 0xDE, 0xCF, 0xDF, 0xEE, 0xFE, 0xEF, 0xFF
334    );
335
336    /**
337     * Inverse IP mapping helper table.
338     * Indexing this table with a byte value reverses the bit order.
339     *
340     * @var array
341     * @access private
342     */
343    var $invipmap = array(
344        0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
345        0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
346        0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
347        0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
348        0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
349        0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
350        0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
351        0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
352        0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
353        0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
354        0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
355        0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
356        0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
357        0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
358        0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
359        0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
360        0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
361        0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
362        0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
363        0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
364        0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
365        0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
366        0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
367        0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
368        0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
369        0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
370        0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
371        0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
372        0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
373        0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
374        0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
375        0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
376    );
377
378    /**
379     * Pre-permuted S-box1
380     *
381     * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
382     * P table: concatenation can then be replaced by exclusive ORs.
383     *
384     * @var array
385     * @access private
386     */
387    var $sbox1 = array(
388        0x00808200, 0x00000000, 0x00008000, 0x00808202,
389        0x00808002, 0x00008202, 0x00000002, 0x00008000,
390        0x00000200, 0x00808200, 0x00808202, 0x00000200,
391        0x00800202, 0x00808002, 0x00800000, 0x00000002,
392        0x00000202, 0x00800200, 0x00800200, 0x00008200,
393        0x00008200, 0x00808000, 0x00808000, 0x00800202,
394        0x00008002, 0x00800002, 0x00800002, 0x00008002,
395        0x00000000, 0x00000202, 0x00008202, 0x00800000,
396        0x00008000, 0x00808202, 0x00000002, 0x00808000,
397        0x00808200, 0x00800000, 0x00800000, 0x00000200,
398        0x00808002, 0x00008000, 0x00008200, 0x00800002,
399        0x00000200, 0x00000002, 0x00800202, 0x00008202,
400        0x00808202, 0x00008002, 0x00808000, 0x00800202,
401        0x00800002, 0x00000202, 0x00008202, 0x00808200,
402        0x00000202, 0x00800200, 0x00800200, 0x00000000,
403        0x00008002, 0x00008200, 0x00000000, 0x00808002
404    );
405
406    /**
407     * Pre-permuted S-box2
408     *
409     * @var array
410     * @access private
411     */
412    var $sbox2 = array(
413        0x40084010, 0x40004000, 0x00004000, 0x00084010,
414        0x00080000, 0x00000010, 0x40080010, 0x40004010,
415        0x40000010, 0x40084010, 0x40084000, 0x40000000,
416        0x40004000, 0x00080000, 0x00000010, 0x40080010,
417        0x00084000, 0x00080010, 0x40004010, 0x00000000,
418        0x40000000, 0x00004000, 0x00084010, 0x40080000,
419        0x00080010, 0x40000010, 0x00000000, 0x00084000,
420        0x00004010, 0x40084000, 0x40080000, 0x00004010,
421        0x00000000, 0x00084010, 0x40080010, 0x00080000,
422        0x40004010, 0x40080000, 0x40084000, 0x00004000,
423        0x40080000, 0x40004000, 0x00000010, 0x40084010,
424        0x00084010, 0x00000010, 0x00004000, 0x40000000,
425        0x00004010, 0x40084000, 0x00080000, 0x40000010,
426        0x00080010, 0x40004010, 0x40000010, 0x00080010,
427        0x00084000, 0x00000000, 0x40004000, 0x00004010,
428        0x40000000, 0x40080010, 0x40084010, 0x00084000
429    );
430
431    /**
432     * Pre-permuted S-box3
433     *
434     * @var array
435     * @access private
436     */
437    var $sbox3 = array(
438        0x00000104, 0x04010100, 0x00000000, 0x04010004,
439        0x04000100, 0x00000000, 0x00010104, 0x04000100,
440        0x00010004, 0x04000004, 0x04000004, 0x00010000,
441        0x04010104, 0x00010004, 0x04010000, 0x00000104,
442        0x04000000, 0x00000004, 0x04010100, 0x00000100,
443        0x00010100, 0x04010000, 0x04010004, 0x00010104,
444        0x04000104, 0x00010100, 0x00010000, 0x04000104,
445        0x00000004, 0x04010104, 0x00000100, 0x04000000,
446        0x04010100, 0x04000000, 0x00010004, 0x00000104,
447        0x00010000, 0x04010100, 0x04000100, 0x00000000,
448        0x00000100, 0x00010004, 0x04010104, 0x04000100,
449        0x04000004, 0x00000100, 0x00000000, 0x04010004,
450        0x04000104, 0x00010000, 0x04000000, 0x04010104,
451        0x00000004, 0x00010104, 0x00010100, 0x04000004,
452        0x04010000, 0x04000104, 0x00000104, 0x04010000,
453        0x00010104, 0x00000004, 0x04010004, 0x00010100
454    );
455
456    /**
457     * Pre-permuted S-box4
458     *
459     * @var array
460     * @access private
461     */
462    var $sbox4 = array(
463        0x80401000, 0x80001040, 0x80001040, 0x00000040,
464        0x00401040, 0x80400040, 0x80400000, 0x80001000,
465        0x00000000, 0x00401000, 0x00401000, 0x80401040,
466        0x80000040, 0x00000000, 0x00400040, 0x80400000,
467        0x80000000, 0x00001000, 0x00400000, 0x80401000,
468        0x00000040, 0x00400000, 0x80001000, 0x00001040,
469        0x80400040, 0x80000000, 0x00001040, 0x00400040,
470        0x00001000, 0x00401040, 0x80401040, 0x80000040,
471        0x00400040, 0x80400000, 0x00401000, 0x80401040,
472        0x80000040, 0x00000000, 0x00000000, 0x00401000,
473        0x00001040, 0x00400040, 0x80400040, 0x80000000,
474        0x80401000, 0x80001040, 0x80001040, 0x00000040,
475        0x80401040, 0x80000040, 0x80000000, 0x00001000,
476        0x80400000, 0x80001000, 0x00401040, 0x80400040,
477        0x80001000, 0x00001040, 0x00400000, 0x80401000,
478        0x00000040, 0x00400000, 0x00001000, 0x00401040
479    );
480
481    /**
482     * Pre-permuted S-box5
483     *
484     * @var array
485     * @access private
486     */
487    var $sbox5 = array(
488        0x00000080, 0x01040080, 0x01040000, 0x21000080,
489        0x00040000, 0x00000080, 0x20000000, 0x01040000,
490        0x20040080, 0x00040000, 0x01000080, 0x20040080,
491        0x21000080, 0x21040000, 0x00040080, 0x20000000,
492        0x01000000, 0x20040000, 0x20040000, 0x00000000,
493        0x20000080, 0x21040080, 0x21040080, 0x01000080,
494        0x21040000, 0x20000080, 0x00000000, 0x21000000,
495        0x01040080, 0x01000000, 0x21000000, 0x00040080,
496        0x00040000, 0x21000080, 0x00000080, 0x01000000,
497        0x20000000, 0x01040000, 0x21000080, 0x20040080,
498        0x01000080, 0x20000000, 0x21040000, 0x01040080,
499        0x20040080, 0x00000080, 0x01000000, 0x21040000,
500        0x21040080, 0x00040080, 0x21000000, 0x21040080,
501        0x01040000, 0x00000000, 0x20040000, 0x21000000,
502        0x00040080, 0x01000080, 0x20000080, 0x00040000,
503        0x00000000, 0x20040000, 0x01040080, 0x20000080
504    );
505
506    /**
507     * Pre-permuted S-box6
508     *
509     * @var array
510     * @access private
511     */
512    var $sbox6 = array(
513        0x10000008, 0x10200000, 0x00002000, 0x10202008,
514        0x10200000, 0x00000008, 0x10202008, 0x00200000,
515        0x10002000, 0x00202008, 0x00200000, 0x10000008,
516        0x00200008, 0x10002000, 0x10000000, 0x00002008,
517        0x00000000, 0x00200008, 0x10002008, 0x00002000,
518        0x00202000, 0x10002008, 0x00000008, 0x10200008,
519        0x10200008, 0x00000000, 0x00202008, 0x10202000,
520        0x00002008, 0x00202000, 0x10202000, 0x10000000,
521        0x10002000, 0x00000008, 0x10200008, 0x00202000,
522        0x10202008, 0x00200000, 0x00002008, 0x10000008,
523        0x00200000, 0x10002000, 0x10000000, 0x00002008,
524        0x10000008, 0x10202008, 0x00202000, 0x10200000,
525        0x00202008, 0x10202000, 0x00000000, 0x10200008,
526        0x00000008, 0x00002000, 0x10200000, 0x00202008,
527        0x00002000, 0x00200008, 0x10002008, 0x00000000,
528        0x10202000, 0x10000000, 0x00200008, 0x10002008
529    );
530
531    /**
532     * Pre-permuted S-box7
533     *
534     * @var array
535     * @access private
536     */
537    var $sbox7 = array(
538        0x00100000, 0x02100001, 0x02000401, 0x00000000,
539        0x00000400, 0x02000401, 0x00100401, 0x02100400,
540        0x02100401, 0x00100000, 0x00000000, 0x02000001,
541        0x00000001, 0x02000000, 0x02100001, 0x00000401,
542        0x02000400, 0x00100401, 0x00100001, 0x02000400,
543        0x02000001, 0x02100000, 0x02100400, 0x00100001,
544        0x02100000, 0x00000400, 0x00000401, 0x02100401,
545        0x00100400, 0x00000001, 0x02000000, 0x00100400,
546        0x02000000, 0x00100400, 0x00100000, 0x02000401,
547        0x02000401, 0x02100001, 0x02100001, 0x00000001,
548        0x00100001, 0x02000000, 0x02000400, 0x00100000,
549        0x02100400, 0x00000401, 0x00100401, 0x02100400,
550        0x00000401, 0x02000001, 0x02100401, 0x02100000,
551        0x00100400, 0x00000000, 0x00000001, 0x02100401,
552        0x00000000, 0x00100401, 0x02100000, 0x00000400,
553        0x02000001, 0x02000400, 0x00000400, 0x00100001
554    );
555
556    /**
557     * Pre-permuted S-box8
558     *
559     * @var array
560     * @access private
561     */
562    var $sbox8 = array(
563        0x08000820, 0x00000800, 0x00020000, 0x08020820,
564        0x08000000, 0x08000820, 0x00000020, 0x08000000,
565        0x00020020, 0x08020000, 0x08020820, 0x00020800,
566        0x08020800, 0x00020820, 0x00000800, 0x00000020,
567        0x08020000, 0x08000020, 0x08000800, 0x00000820,
568        0x00020800, 0x00020020, 0x08020020, 0x08020800,
569        0x00000820, 0x00000000, 0x00000000, 0x08020020,
570        0x08000020, 0x08000800, 0x00020820, 0x00020000,
571        0x00020820, 0x00020000, 0x08020800, 0x00000800,
572        0x00000020, 0x08020020, 0x00000800, 0x00020820,
573        0x08000800, 0x00000020, 0x08000020, 0x08020000,
574        0x08020020, 0x08000000, 0x00020000, 0x08000820,
575        0x00000000, 0x08020820, 0x00020020, 0x08000020,
576        0x08020000, 0x08000800, 0x08000820, 0x00000000,
577        0x08020820, 0x00020800, 0x00020800, 0x00000820,
578        0x00000820, 0x00020020, 0x08000000, 0x08020800
579    );
580
581    /**
582     * Test for engine validity
583     *
584     * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
585     *
586     * @see \phpseclib\Crypt\Base::isValidEngine()
587     * @param int $engine
588     * @access public
589     * @return bool
590     */
591    function isValidEngine($engine)
592    {
593        if ($this->key_length_max == 8) {
594            if ($engine == self::ENGINE_OPENSSL) {
595                $this->cipher_name_openssl_ecb = 'des-ecb';
596                $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
597            }
598        }
599
600        return parent::isValidEngine($engine);
601    }
602
603    /**
604     * Sets the key.
605     *
606     * Keys can be of any length.  DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
607     * only use the first eight, if $key has more then eight characters in it, and pad $key with the
608     * null byte if it is less then eight characters long.
609     *
610     * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
611     *
612     * If the key is not explicitly set, it'll be assumed to be all zero's.
613     *
614     * @see \phpseclib\Crypt\Base::setKey()
615     * @access public
616     * @param string $key
617     */
618    function setKey($key)
619    {
620        // We check/cut here only up to max length of the key.
621        // Key padding to the proper length will be done in _setupKey()
622        if (strlen($key) > $this->key_length_max) {
623            $key = substr($key, 0, $this->key_length_max);
624        }
625
626        // Sets the key
627        parent::setKey($key);
628    }
629
630    /**
631     * Encrypts a block
632     *
633     * @see \phpseclib\Crypt\Base::_encryptBlock()
634     * @see \phpseclib\Crypt\Base::encrypt()
635     * @see self::encrypt()
636     * @access private
637     * @param string $in
638     * @return string
639     */
640    function _encryptBlock($in)
641    {
642        return $this->_processBlock($in, self::ENCRYPT);
643    }
644
645    /**
646     * Decrypts a block
647     *
648     * @see \phpseclib\Crypt\Base::_decryptBlock()
649     * @see \phpseclib\Crypt\Base::decrypt()
650     * @see self::decrypt()
651     * @access private
652     * @param string $in
653     * @return string
654     */
655    function _decryptBlock($in)
656    {
657        return $this->_processBlock($in, self::DECRYPT);
658    }
659
660    /**
661     * Encrypts or decrypts a 64-bit block
662     *
663     * $mode should be either self::ENCRYPT or self::DECRYPT.  See
664     * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
665     * idea of what this function does.
666     *
667     * @see self::_encryptBlock()
668     * @see self::_decryptBlock()
669     * @access private
670     * @param string $block
671     * @param int $mode
672     * @return string
673     */
674    function _processBlock($block, $mode)
675    {
676        static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
677        if (!$sbox1) {
678            $sbox1 = array_map("intval", $this->sbox1);
679            $sbox2 = array_map("intval", $this->sbox2);
680            $sbox3 = array_map("intval", $this->sbox3);
681            $sbox4 = array_map("intval", $this->sbox4);
682            $sbox5 = array_map("intval", $this->sbox5);
683            $sbox6 = array_map("intval", $this->sbox6);
684            $sbox7 = array_map("intval", $this->sbox7);
685            $sbox8 = array_map("intval", $this->sbox8);
686            /* Merge $shuffle with $[inv]ipmap */
687            for ($i = 0; $i < 256; ++$i) {
688                $shuffleip[]    =  $this->shuffle[$this->ipmap[$i]];
689                $shuffleinvip[] =  $this->shuffle[$this->invipmap[$i]];
690            }
691        }
692
693        $keys  = $this->keys[$mode];
694        $ki    = -1;
695
696        // Do the initial IP permutation.
697        $t = unpack('Nl/Nr', $block);
698        list($l, $r) = array($t['l'], $t['r']);
699        $block = ($shuffleip[ $r        & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
700                 ($shuffleip[($r >>  8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
701                 ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
702                 ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
703                 ($shuffleip[ $l        & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
704                 ($shuffleip[($l >>  8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
705                 ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
706                 ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
707
708        // Extract L0 and R0.
709        $t = unpack('Nl/Nr', $block);
710        list($l, $r) = array($t['l'], $t['r']);
711
712        for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
713            // Perform the 16 steps.
714            for ($i = 0; $i < 16; $i++) {
715                // start of "the Feistel (F) function" - see the following URL:
716                // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
717                // Merge key schedule.
718                $b1 = (($r >>  3) & 0x1FFFFFFF) ^ ($r << 29) ^ $keys[++$ki];
719                $b2 = (($r >> 31) & 0x00000001) ^ ($r <<  1) ^ $keys[++$ki];
720
721                // S-box indexing.
722                $t = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
723                     $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
724                     $sbox5[($b1 >>  8) & 0x3F] ^ $sbox6[($b2 >>  8) & 0x3F] ^
725                     $sbox7[ $b1        & 0x3F] ^ $sbox8[ $b2        & 0x3F] ^ $l;
726                // end of "the Feistel (F) function"
727
728                $l = $r;
729                $r = $t;
730            }
731
732            // Last step should not permute L & R.
733            $t = $l;
734            $l = $r;
735            $r = $t;
736        }
737
738        // Perform the inverse IP permutation.
739        return ($shuffleinvip[($r >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
740               ($shuffleinvip[($l >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
741               ($shuffleinvip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
742               ($shuffleinvip[($l >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
743               ($shuffleinvip[($r >>  8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
744               ($shuffleinvip[($l >>  8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
745               ($shuffleinvip[ $r        & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
746               ($shuffleinvip[ $l        & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
747    }
748
749    /**
750     * Creates the key schedule
751     *
752     * @see \phpseclib\Crypt\Base::_setupKey()
753     * @access private
754     */
755    function _setupKey()
756    {
757        if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) {
758            // already expanded
759            return;
760        }
761        $this->kl = array('key' => $this->key, 'des_rounds' => $this->des_rounds);
762
763        static $shifts = array( // number of key bits shifted per round
764            1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
765        );
766
767        static $pc1map = array(
768            0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C,
769            0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E,
770            0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1C, 0x1C,
771            0x12, 0x12, 0x1A, 0x1A, 0x16, 0x16, 0x1E, 0x1E,
772            0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2C, 0x2C,
773            0x22, 0x22, 0x2A, 0x2A, 0x26, 0x26, 0x2E, 0x2E,
774            0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3C, 0x3C,
775            0x32, 0x32, 0x3A, 0x3A, 0x36, 0x36, 0x3E, 0x3E,
776            0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4C, 0x4C,
777            0x42, 0x42, 0x4A, 0x4A, 0x46, 0x46, 0x4E, 0x4E,
778            0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5C, 0x5C,
779            0x52, 0x52, 0x5A, 0x5A, 0x56, 0x56, 0x5E, 0x5E,
780            0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6C, 0x6C,
781            0x62, 0x62, 0x6A, 0x6A, 0x66, 0x66, 0x6E, 0x6E,
782            0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7C, 0x7C,
783            0x72, 0x72, 0x7A, 0x7A, 0x76, 0x76, 0x7E, 0x7E,
784            0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8C, 0x8C,
785            0x82, 0x82, 0x8A, 0x8A, 0x86, 0x86, 0x8E, 0x8E,
786            0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9C, 0x9C,
787            0x92, 0x92, 0x9A, 0x9A, 0x96, 0x96, 0x9E, 0x9E,
788            0xA0, 0xA0, 0xA8, 0xA8, 0xA4, 0xA4, 0xAC, 0xAC,
789            0xA2, 0xA2, 0xAA, 0xAA, 0xA6, 0xA6, 0xAE, 0xAE,
790            0xB0, 0xB0, 0xB8, 0xB8, 0xB4, 0xB4, 0xBC, 0xBC,
791            0xB2, 0xB2, 0xBA, 0xBA, 0xB6, 0xB6, 0xBE, 0xBE,
792            0xC0, 0xC0, 0xC8, 0xC8, 0xC4, 0xC4, 0xCC, 0xCC,
793            0xC2, 0xC2, 0xCA, 0xCA, 0xC6, 0xC6, 0xCE, 0xCE,
794            0xD0, 0xD0, 0xD8, 0xD8, 0xD4, 0xD4, 0xDC, 0xDC,
795            0xD2, 0xD2, 0xDA, 0xDA, 0xD6, 0xD6, 0xDE, 0xDE,
796            0xE0, 0xE0, 0xE8, 0xE8, 0xE4, 0xE4, 0xEC, 0xEC,
797            0xE2, 0xE2, 0xEA, 0xEA, 0xE6, 0xE6, 0xEE, 0xEE,
798            0xF0, 0xF0, 0xF8, 0xF8, 0xF4, 0xF4, 0xFC, 0xFC,
799            0xF2, 0xF2, 0xFA, 0xFA, 0xF6, 0xF6, 0xFE, 0xFE
800        );
801
802        // Mapping tables for the PC-2 transformation.
803        static $pc2mapc1 = array(
804            0x00000000, 0x00000400, 0x00200000, 0x00200400,
805            0x00000001, 0x00000401, 0x00200001, 0x00200401,
806            0x02000000, 0x02000400, 0x02200000, 0x02200400,
807            0x02000001, 0x02000401, 0x02200001, 0x02200401
808        );
809        static $pc2mapc2 = array(
810            0x00000000, 0x00000800, 0x08000000, 0x08000800,
811            0x00010000, 0x00010800, 0x08010000, 0x08010800,
812            0x00000000, 0x00000800, 0x08000000, 0x08000800,
813            0x00010000, 0x00010800, 0x08010000, 0x08010800,
814            0x00000100, 0x00000900, 0x08000100, 0x08000900,
815            0x00010100, 0x00010900, 0x08010100, 0x08010900,
816            0x00000100, 0x00000900, 0x08000100, 0x08000900,
817            0x00010100, 0x00010900, 0x08010100, 0x08010900,
818            0x00000010, 0x00000810, 0x08000010, 0x08000810,
819            0x00010010, 0x00010810, 0x08010010, 0x08010810,
820            0x00000010, 0x00000810, 0x08000010, 0x08000810,
821            0x00010010, 0x00010810, 0x08010010, 0x08010810,
822            0x00000110, 0x00000910, 0x08000110, 0x08000910,
823            0x00010110, 0x00010910, 0x08010110, 0x08010910,
824            0x00000110, 0x00000910, 0x08000110, 0x08000910,
825            0x00010110, 0x00010910, 0x08010110, 0x08010910,
826            0x00040000, 0x00040800, 0x08040000, 0x08040800,
827            0x00050000, 0x00050800, 0x08050000, 0x08050800,
828            0x00040000, 0x00040800, 0x08040000, 0x08040800,
829            0x00050000, 0x00050800, 0x08050000, 0x08050800,
830            0x00040100, 0x00040900, 0x08040100, 0x08040900,
831            0x00050100, 0x00050900, 0x08050100, 0x08050900,
832            0x00040100, 0x00040900, 0x08040100, 0x08040900,
833            0x00050100, 0x00050900, 0x08050100, 0x08050900,
834            0x00040010, 0x00040810, 0x08040010, 0x08040810,
835            0x00050010, 0x00050810, 0x08050010, 0x08050810,
836            0x00040010, 0x00040810, 0x08040010, 0x08040810,
837            0x00050010, 0x00050810, 0x08050010, 0x08050810,
838            0x00040110, 0x00040910, 0x08040110, 0x08040910,
839            0x00050110, 0x00050910, 0x08050110, 0x08050910,
840            0x00040110, 0x00040910, 0x08040110, 0x08040910,
841            0x00050110, 0x00050910, 0x08050110, 0x08050910,
842            0x01000000, 0x01000800, 0x09000000, 0x09000800,
843            0x01010000, 0x01010800, 0x09010000, 0x09010800,
844            0x01000000, 0x01000800, 0x09000000, 0x09000800,
845            0x01010000, 0x01010800, 0x09010000, 0x09010800,
846            0x01000100, 0x01000900, 0x09000100, 0x09000900,
847            0x01010100, 0x01010900, 0x09010100, 0x09010900,
848            0x01000100, 0x01000900, 0x09000100, 0x09000900,
849            0x01010100, 0x01010900, 0x09010100, 0x09010900,
850            0x01000010, 0x01000810, 0x09000010, 0x09000810,
851            0x01010010, 0x01010810, 0x09010010, 0x09010810,
852            0x01000010, 0x01000810, 0x09000010, 0x09000810,
853            0x01010010, 0x01010810, 0x09010010, 0x09010810,
854            0x01000110, 0x01000910, 0x09000110, 0x09000910,
855            0x01010110, 0x01010910, 0x09010110, 0x09010910,
856            0x01000110, 0x01000910, 0x09000110, 0x09000910,
857            0x01010110, 0x01010910, 0x09010110, 0x09010910,
858            0x01040000, 0x01040800, 0x09040000, 0x09040800,
859            0x01050000, 0x01050800, 0x09050000, 0x09050800,
860            0x01040000, 0x01040800, 0x09040000, 0x09040800,
861            0x01050000, 0x01050800, 0x09050000, 0x09050800,
862            0x01040100, 0x01040900, 0x09040100, 0x09040900,
863            0x01050100, 0x01050900, 0x09050100, 0x09050900,
864            0x01040100, 0x01040900, 0x09040100, 0x09040900,
865            0x01050100, 0x01050900, 0x09050100, 0x09050900,
866            0x01040010, 0x01040810, 0x09040010, 0x09040810,
867            0x01050010, 0x01050810, 0x09050010, 0x09050810,
868            0x01040010, 0x01040810, 0x09040010, 0x09040810,
869            0x01050010, 0x01050810, 0x09050010, 0x09050810,
870            0x01040110, 0x01040910, 0x09040110, 0x09040910,
871            0x01050110, 0x01050910, 0x09050110, 0x09050910,
872            0x01040110, 0x01040910, 0x09040110, 0x09040910,
873            0x01050110, 0x01050910, 0x09050110, 0x09050910
874        );
875        static $pc2mapc3 = array(
876            0x00000000, 0x00000004, 0x00001000, 0x00001004,
877            0x00000000, 0x00000004, 0x00001000, 0x00001004,
878            0x10000000, 0x10000004, 0x10001000, 0x10001004,
879            0x10000000, 0x10000004, 0x10001000, 0x10001004,
880            0x00000020, 0x00000024, 0x00001020, 0x00001024,
881            0x00000020, 0x00000024, 0x00001020, 0x00001024,
882            0x10000020, 0x10000024, 0x10001020, 0x10001024,
883            0x10000020, 0x10000024, 0x10001020, 0x10001024,
884            0x00080000, 0x00080004, 0x00081000, 0x00081004,
885            0x00080000, 0x00080004, 0x00081000, 0x00081004,
886            0x10080000, 0x10080004, 0x10081000, 0x10081004,
887            0x10080000, 0x10080004, 0x10081000, 0x10081004,
888            0x00080020, 0x00080024, 0x00081020, 0x00081024,
889            0x00080020, 0x00080024, 0x00081020, 0x00081024,
890            0x10080020, 0x10080024, 0x10081020, 0x10081024,
891            0x10080020, 0x10080024, 0x10081020, 0x10081024,
892            0x20000000, 0x20000004, 0x20001000, 0x20001004,
893            0x20000000, 0x20000004, 0x20001000, 0x20001004,
894            0x30000000, 0x30000004, 0x30001000, 0x30001004,
895            0x30000000, 0x30000004, 0x30001000, 0x30001004,
896            0x20000020, 0x20000024, 0x20001020, 0x20001024,
897            0x20000020, 0x20000024, 0x20001020, 0x20001024,
898            0x30000020, 0x30000024, 0x30001020, 0x30001024,
899            0x30000020, 0x30000024, 0x30001020, 0x30001024,
900            0x20080000, 0x20080004, 0x20081000, 0x20081004,
901            0x20080000, 0x20080004, 0x20081000, 0x20081004,
902            0x30080000, 0x30080004, 0x30081000, 0x30081004,
903            0x30080000, 0x30080004, 0x30081000, 0x30081004,
904            0x20080020, 0x20080024, 0x20081020, 0x20081024,
905            0x20080020, 0x20080024, 0x20081020, 0x20081024,
906            0x30080020, 0x30080024, 0x30081020, 0x30081024,
907            0x30080020, 0x30080024, 0x30081020, 0x30081024,
908            0x00000002, 0x00000006, 0x00001002, 0x00001006,
909            0x00000002, 0x00000006, 0x00001002, 0x00001006,
910            0x10000002, 0x10000006, 0x10001002, 0x10001006,
911            0x10000002, 0x10000006, 0x10001002, 0x10001006,
912            0x00000022, 0x00000026, 0x00001022, 0x00001026,
913            0x00000022, 0x00000026, 0x00001022, 0x00001026,
914            0x10000022, 0x10000026, 0x10001022, 0x10001026,
915            0x10000022, 0x10000026, 0x10001022, 0x10001026,
916            0x00080002, 0x00080006, 0x00081002, 0x00081006,
917            0x00080002, 0x00080006, 0x00081002, 0x00081006,
918            0x10080002, 0x10080006, 0x10081002, 0x10081006,
919            0x10080002, 0x10080006, 0x10081002, 0x10081006,
920            0x00080022, 0x00080026, 0x00081022, 0x00081026,
921            0x00080022, 0x00080026, 0x00081022, 0x00081026,
922            0x10080022, 0x10080026, 0x10081022, 0x10081026,
923            0x10080022, 0x10080026, 0x10081022, 0x10081026,
924            0x20000002, 0x20000006, 0x20001002, 0x20001006,
925            0x20000002, 0x20000006, 0x20001002, 0x20001006,
926            0x30000002, 0x30000006, 0x30001002, 0x30001006,
927            0x30000002, 0x30000006, 0x30001002, 0x30001006,
928            0x20000022, 0x20000026, 0x20001022, 0x20001026,
929            0x20000022, 0x20000026, 0x20001022, 0x20001026,
930            0x30000022, 0x30000026, 0x30001022, 0x30001026,
931            0x30000022, 0x30000026, 0x30001022, 0x30001026,
932            0x20080002, 0x20080006, 0x20081002, 0x20081006,
933            0x20080002, 0x20080006, 0x20081002, 0x20081006,
934            0x30080002, 0x30080006, 0x30081002, 0x30081006,
935            0x30080002, 0x30080006, 0x30081002, 0x30081006,
936            0x20080022, 0x20080026, 0x20081022, 0x20081026,
937            0x20080022, 0x20080026, 0x20081022, 0x20081026,
938            0x30080022, 0x30080026, 0x30081022, 0x30081026,
939            0x30080022, 0x30080026, 0x30081022, 0x30081026
940        );
941        static $pc2mapc4 = array(
942            0x00000000, 0x00100000, 0x00000008, 0x00100008,
943            0x00000200, 0x00100200, 0x00000208, 0x00100208,
944            0x00000000, 0x00100000, 0x00000008, 0x00100008,
945            0x00000200, 0x00100200, 0x00000208, 0x00100208,
946            0x04000000, 0x04100000, 0x04000008, 0x04100008,
947            0x04000200, 0x04100200, 0x04000208, 0x04100208,
948            0x04000000, 0x04100000, 0x04000008, 0x04100008,
949            0x04000200, 0x04100200, 0x04000208, 0x04100208,
950            0x00002000, 0x00102000, 0x00002008, 0x00102008,
951            0x00002200, 0x00102200, 0x00002208, 0x00102208,
952            0x00002000, 0x00102000, 0x00002008, 0x00102008,
953            0x00002200, 0x00102200, 0x00002208, 0x00102208,
954            0x04002000, 0x04102000, 0x04002008, 0x04102008,
955            0x04002200, 0x04102200, 0x04002208, 0x04102208,
956            0x04002000, 0x04102000, 0x04002008, 0x04102008,
957            0x04002200, 0x04102200, 0x04002208, 0x04102208,
958            0x00000000, 0x00100000, 0x00000008, 0x00100008,
959            0x00000200, 0x00100200, 0x00000208, 0x00100208,
960            0x00000000, 0x00100000, 0x00000008, 0x00100008,
961            0x00000200, 0x00100200, 0x00000208, 0x00100208,
962            0x04000000, 0x04100000, 0x04000008, 0x04100008,
963            0x04000200, 0x04100200, 0x04000208, 0x04100208,
964            0x04000000, 0x04100000, 0x04000008, 0x04100008,
965            0x04000200, 0x04100200, 0x04000208, 0x04100208,
966            0x00002000, 0x00102000, 0x00002008, 0x00102008,
967            0x00002200, 0x00102200, 0x00002208, 0x00102208,
968            0x00002000, 0x00102000, 0x00002008, 0x00102008,
969            0x00002200, 0x00102200, 0x00002208, 0x00102208,
970            0x04002000, 0x04102000, 0x04002008, 0x04102008,
971            0x04002200, 0x04102200, 0x04002208, 0x04102208,
972            0x04002000, 0x04102000, 0x04002008, 0x04102008,
973            0x04002200, 0x04102200, 0x04002208, 0x04102208,
974            0x00020000, 0x00120000, 0x00020008, 0x00120008,
975            0x00020200, 0x00120200, 0x00020208, 0x00120208,
976            0x00020000, 0x00120000, 0x00020008, 0x00120008,
977            0x00020200, 0x00120200, 0x00020208, 0x00120208,
978            0x04020000, 0x04120000, 0x04020008, 0x04120008,
979            0x04020200, 0x04120200, 0x04020208, 0x04120208,
980            0x04020000, 0x04120000, 0x04020008, 0x04120008,
981            0x04020200, 0x04120200, 0x04020208, 0x04120208,
982            0x00022000, 0x00122000, 0x00022008, 0x00122008,
983            0x00022200, 0x00122200, 0x00022208, 0x00122208,
984            0x00022000, 0x00122000, 0x00022008, 0x00122008,
985            0x00022200, 0x00122200, 0x00022208, 0x00122208,
986            0x04022000, 0x04122000, 0x04022008, 0x04122008,
987            0x04022200, 0x04122200, 0x04022208, 0x04122208,
988            0x04022000, 0x04122000, 0x04022008, 0x04122008,
989            0x04022200, 0x04122200, 0x04022208, 0x04122208,
990            0x00020000, 0x00120000, 0x00020008, 0x00120008,
991            0x00020200, 0x00120200, 0x00020208, 0x00120208,
992            0x00020000, 0x00120000, 0x00020008, 0x00120008,
993            0x00020200, 0x00120200, 0x00020208, 0x00120208,
994            0x04020000, 0x04120000, 0x04020008, 0x04120008,
995            0x04020200, 0x04120200, 0x04020208, 0x04120208,
996            0x04020000, 0x04120000, 0x04020008, 0x04120008,
997            0x04020200, 0x04120200, 0x04020208, 0x04120208,
998            0x00022000, 0x00122000, 0x00022008, 0x00122008,
999            0x00022200, 0x00122200, 0x00022208, 0x00122208,
1000            0x00022000, 0x00122000, 0x00022008, 0x00122008,
1001            0x00022200, 0x00122200, 0x00022208, 0x00122208,
1002            0x04022000, 0x04122000, 0x04022008, 0x04122008,
1003            0x04022200, 0x04122200, 0x04022208, 0x04122208,
1004            0x04022000, 0x04122000, 0x04022008, 0x04122008,
1005            0x04022200, 0x04122200, 0x04022208, 0x04122208
1006        );
1007        static $pc2mapd1 = array(
1008            0x00000000, 0x00000001, 0x08000000, 0x08000001,
1009            0x00200000, 0x00200001, 0x08200000, 0x08200001,
1010            0x00000002, 0x00000003, 0x08000002, 0x08000003,
1011            0x00200002, 0x00200003, 0x08200002, 0x08200003
1012        );
1013        static $pc2mapd2 = array(
1014            0x00000000, 0x00100000, 0x00000800, 0x00100800,
1015            0x00000000, 0x00100000, 0x00000800, 0x00100800,
1016            0x04000000, 0x04100000, 0x04000800, 0x04100800,
1017            0x04000000, 0x04100000, 0x04000800, 0x04100800,
1018            0x00000004, 0x00100004, 0x00000804, 0x00100804,
1019            0x00000004, 0x00100004, 0x00000804, 0x00100804,
1020            0x04000004, 0x04100004, 0x04000804, 0x04100804,
1021            0x04000004, 0x04100004, 0x04000804, 0x04100804,
1022            0x00000000, 0x00100000, 0x00000800, 0x00100800,
1023            0x00000000, 0x00100000, 0x00000800, 0x00100800,
1024            0x04000000, 0x04100000, 0x04000800, 0x04100800,
1025            0x04000000, 0x04100000, 0x04000800, 0x04100800,
1026            0x00000004, 0x00100004, 0x00000804, 0x00100804,
1027            0x00000004, 0x00100004, 0x00000804, 0x00100804,
1028            0x04000004, 0x04100004, 0x04000804, 0x04100804,
1029            0x04000004, 0x04100004, 0x04000804, 0x04100804,
1030            0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1031            0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1032            0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1033            0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1034            0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1035            0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1036            0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1037            0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1038            0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1039            0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1040            0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1041            0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1042            0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1043            0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1044            0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1045            0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1046            0x00020000, 0x00120000, 0x00020800, 0x00120800,
1047            0x00020000, 0x00120000, 0x00020800, 0x00120800,
1048            0x04020000, 0x04120000, 0x04020800, 0x04120800,
1049            0x04020000, 0x04120000, 0x04020800, 0x04120800,
1050            0x00020004, 0x00120004, 0x00020804, 0x00120804,
1051            0x00020004, 0x00120004, 0x00020804, 0x00120804,
1052            0x04020004, 0x04120004, 0x04020804, 0x04120804,
1053            0x04020004, 0x04120004, 0x04020804, 0x04120804,
1054            0x00020000, 0x00120000, 0x00020800, 0x00120800,
1055            0x00020000, 0x00120000, 0x00020800, 0x00120800,
1056            0x04020000, 0x04120000, 0x04020800, 0x04120800,
1057            0x04020000, 0x04120000, 0x04020800, 0x04120800,
1058            0x00020004, 0x00120004, 0x00020804, 0x00120804,
1059            0x00020004, 0x00120004, 0x00020804, 0x00120804,
1060            0x04020004, 0x04120004, 0x04020804, 0x04120804,
1061            0x04020004, 0x04120004, 0x04020804, 0x04120804,
1062            0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1063            0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1064            0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1065            0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1066            0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1067            0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1068            0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
1069            0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
1070            0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1071            0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1072            0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1073            0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1074            0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1075            0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1076            0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
1077            0x04020204, 0x04120204, 0x04020A04, 0x04120A04
1078        );
1079        static $pc2mapd3 = array(
1080            0x00000000, 0x00010000, 0x02000000, 0x02010000,
1081            0x00000020, 0x00010020, 0x02000020, 0x02010020,
1082            0x00040000, 0x00050000, 0x02040000, 0x02050000,
1083            0x00040020, 0x00050020, 0x02040020, 0x02050020,
1084            0x00002000, 0x00012000, 0x02002000, 0x02012000,
1085            0x00002020, 0x00012020, 0x02002020, 0x02012020,
1086            0x00042000, 0x00052000, 0x02042000, 0x02052000,
1087            0x00042020, 0x00052020, 0x02042020, 0x02052020,
1088            0x00000000, 0x00010000, 0x02000000, 0x02010000,
1089            0x00000020, 0x00010020, 0x02000020, 0x02010020,
1090            0x00040000, 0x00050000, 0x02040000, 0x02050000,
1091            0x00040020, 0x00050020, 0x02040020, 0x02050020,
1092            0x00002000, 0x00012000, 0x02002000, 0x02012000,
1093            0x00002020, 0x00012020, 0x02002020, 0x02012020,
1094            0x00042000, 0x00052000, 0x02042000, 0x02052000,
1095            0x00042020, 0x00052020, 0x02042020, 0x02052020,
1096            0x00000010, 0x00010010, 0x02000010, 0x02010010,
1097            0x00000030, 0x00010030, 0x02000030, 0x02010030,
1098            0x00040010, 0x00050010, 0x02040010, 0x02050010,
1099            0x00040030, 0x00050030, 0x02040030, 0x02050030,
1100            0x00002010, 0x00012010, 0x02002010, 0x02012010,
1101            0x00002030, 0x00012030, 0x02002030, 0x02012030,
1102            0x00042010, 0x00052010, 0x02042010, 0x02052010,
1103            0x00042030, 0x00052030, 0x02042030, 0x02052030,
1104            0x00000010, 0x00010010, 0x02000010, 0x02010010,
1105            0x00000030, 0x00010030, 0x02000030, 0x02010030,
1106            0x00040010, 0x00050010, 0x02040010, 0x02050010,
1107            0x00040030, 0x00050030, 0x02040030, 0x02050030,
1108            0x00002010, 0x00012010, 0x02002010, 0x02012010,
1109            0x00002030, 0x00012030, 0x02002030, 0x02012030,
1110            0x00042010, 0x00052010, 0x02042010, 0x02052010,
1111            0x00042030, 0x00052030, 0x02042030, 0x02052030,
1112            0x20000000, 0x20010000, 0x22000000, 0x22010000,
1113            0x20000020, 0x20010020, 0x22000020, 0x22010020,
1114            0x20040000, 0x20050000, 0x22040000, 0x22050000,
1115            0x20040020, 0x20050020, 0x22040020, 0x22050020,
1116            0x20002000, 0x20012000, 0x22002000, 0x22012000,
1117            0x20002020, 0x20012020, 0x22002020, 0x22012020,
1118            0x20042000, 0x20052000, 0x22042000, 0x22052000,
1119            0x20042020, 0x20052020, 0x22042020, 0x22052020,
1120            0x20000000, 0x20010000, 0x22000000, 0x22010000,
1121            0x20000020, 0x20010020, 0x22000020, 0x22010020,
1122            0x20040000, 0x20050000, 0x22040000, 0x22050000,
1123            0x20040020, 0x20050020, 0x22040020, 0x22050020,
1124            0x20002000, 0x20012000, 0x22002000, 0x22012000,
1125            0x20002020, 0x20012020, 0x22002020, 0x22012020,
1126            0x20042000, 0x20052000, 0x22042000, 0x22052000,
1127            0x20042020, 0x20052020, 0x22042020, 0x22052020,
1128            0x20000010, 0x20010010, 0x22000010, 0x22010010,
1129            0x20000030, 0x20010030, 0x22000030, 0x22010030,
1130            0x20040010, 0x20050010, 0x22040010, 0x22050010,
1131            0x20040030, 0x20050030, 0x22040030, 0x22050030,
1132            0x20002010, 0x20012010, 0x22002010, 0x22012010,
1133            0x20002030, 0x20012030, 0x22002030, 0x22012030,
1134            0x20042010, 0x20052010, 0x22042010, 0x22052010,
1135            0x20042030, 0x20052030, 0x22042030, 0x22052030,
1136            0x20000010, 0x20010010, 0x22000010, 0x22010010,
1137            0x20000030, 0x20010030, 0x22000030, 0x22010030,
1138            0x20040010, 0x20050010, 0x22040010, 0x22050010,
1139            0x20040030, 0x20050030, 0x22040030, 0x22050030,
1140            0x20002010, 0x20012010, 0x22002010, 0x22012010,
1141            0x20002030, 0x20012030, 0x22002030, 0x22012030,
1142            0x20042010, 0x20052010, 0x22042010, 0x22052010,
1143            0x20042030, 0x20052030, 0x22042030, 0x22052030
1144        );
1145        static $pc2mapd4 = array(
1146            0x00000000, 0x00000400, 0x01000000, 0x01000400,
1147            0x00000000, 0x00000400, 0x01000000, 0x01000400,
1148            0x00000100, 0x00000500, 0x01000100, 0x01000500,
1149            0x00000100, 0x00000500, 0x01000100, 0x01000500,
1150            0x10000000, 0x10000400, 0x11000000, 0x11000400,
1151            0x10000000, 0x10000400, 0x11000000, 0x11000400,
1152            0x10000100, 0x10000500, 0x11000100, 0x11000500,
1153            0x10000100, 0x10000500, 0x11000100, 0x11000500,
1154            0x00080000, 0x00080400, 0x01080000, 0x01080400,
1155            0x00080000, 0x00080400, 0x01080000, 0x01080400,
1156            0x00080100, 0x00080500, 0x01080100, 0x01080500,
1157            0x00080100, 0x00080500, 0x01080100, 0x01080500,
1158            0x10080000, 0x10080400, 0x11080000, 0x11080400,
1159            0x10080000, 0x10080400, 0x11080000, 0x11080400,
1160            0x10080100, 0x10080500, 0x11080100, 0x11080500,
1161            0x10080100, 0x10080500, 0x11080100, 0x11080500,
1162            0x00000008, 0x00000408, 0x01000008, 0x01000408,
1163            0x00000008, 0x00000408, 0x01000008, 0x01000408,
1164            0x00000108, 0x00000508, 0x01000108, 0x01000508,
1165            0x00000108, 0x00000508, 0x01000108, 0x01000508,
1166            0x10000008, 0x10000408, 0x11000008, 0x11000408,
1167            0x10000008, 0x10000408, 0x11000008, 0x11000408,
1168            0x10000108, 0x10000508, 0x11000108, 0x11000508,
1169            0x10000108, 0x10000508, 0x11000108, 0x11000508,
1170            0x00080008, 0x00080408, 0x01080008, 0x01080408,
1171            0x00080008, 0x00080408, 0x01080008, 0x01080408,
1172            0x00080108, 0x00080508, 0x01080108, 0x01080508,
1173            0x00080108, 0x00080508, 0x01080108, 0x01080508,
1174            0x10080008, 0x10080408, 0x11080008, 0x11080408,
1175            0x10080008, 0x10080408, 0x11080008, 0x11080408,
1176            0x10080108, 0x10080508, 0x11080108, 0x11080508,
1177            0x10080108, 0x10080508, 0x11080108, 0x11080508,
1178            0x00001000, 0x00001400, 0x01001000, 0x01001400,
1179            0x00001000, 0x00001400, 0x01001000, 0x01001400,
1180            0x00001100, 0x00001500, 0x01001100, 0x01001500,
1181            0x00001100, 0x00001500, 0x01001100, 0x01001500,
1182            0x10001000, 0x10001400, 0x11001000, 0x11001400,
1183            0x10001000, 0x10001400, 0x11001000, 0x11001400,
1184            0x10001100, 0x10001500, 0x11001100, 0x11001500,
1185            0x10001100, 0x10001500, 0x11001100, 0x11001500,
1186            0x00081000, 0x00081400, 0x01081000, 0x01081400,
1187            0x00081000, 0x00081400, 0x01081000, 0x01081400,
1188            0x00081100, 0x00081500, 0x01081100, 0x01081500,
1189            0x00081100, 0x00081500, 0x01081100, 0x01081500,
1190            0x10081000, 0x10081400, 0x11081000, 0x11081400,
1191            0x10081000, 0x10081400, 0x11081000, 0x11081400,
1192            0x10081100, 0x10081500, 0x11081100, 0x11081500,
1193            0x10081100, 0x10081500, 0x11081100, 0x11081500,
1194            0x00001008, 0x00001408, 0x01001008, 0x01001408,
1195            0x00001008, 0x00001408, 0x01001008, 0x01001408,
1196            0x00001108, 0x00001508, 0x01001108, 0x01001508,
1197            0x00001108, 0x00001508, 0x01001108, 0x01001508,
1198            0x10001008, 0x10001408, 0x11001008, 0x11001408,
1199            0x10001008, 0x10001408, 0x11001008, 0x11001408,
1200            0x10001108, 0x10001508, 0x11001108, 0x11001508,
1201            0x10001108, 0x10001508, 0x11001108, 0x11001508,
1202            0x00081008, 0x00081408, 0x01081008, 0x01081408,
1203            0x00081008, 0x00081408, 0x01081008, 0x01081408,
1204            0x00081108, 0x00081508, 0x01081108, 0x01081508,
1205            0x00081108, 0x00081508, 0x01081108, 0x01081508,
1206            0x10081008, 0x10081408, 0x11081008, 0x11081408,
1207            0x10081008, 0x10081408, 0x11081008, 0x11081408,
1208            0x10081108, 0x10081508, 0x11081108, 0x11081508,
1209            0x10081108, 0x10081508, 0x11081108, 0x11081508
1210        );
1211
1212        $keys = array();
1213        for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
1214            // pad the key and remove extra characters as appropriate.
1215            $key = str_pad(substr($this->key, $des_round * 8, 8), 8, "\0");
1216
1217            // Perform the PC/1 transformation and compute C and D.
1218            $t = unpack('Nl/Nr', $key);
1219            list($l, $r) = array($t['l'], $t['r']);
1220            $key = ($this->shuffle[$pc1map[ $r        & 0xFF]] & "\x80\x80\x80\x80\x80\x80\x80\x00") |
1221                   ($this->shuffle[$pc1map[($r >>  8) & 0xFF]] & "\x40\x40\x40\x40\x40\x40\x40\x00") |
1222                   ($this->shuffle[$pc1map[($r >> 16) & 0xFF]] & "\x20\x20\x20\x20\x20\x20\x20\x00") |
1223                   ($this->shuffle[$pc1map[($r >> 24) & 0xFF]] & "\x10\x10\x10\x10\x10\x10\x10\x00") |
1224                   ($this->shuffle[$pc1map[ $l        & 0xFF]] & "\x08\x08\x08\x08\x08\x08\x08\x00") |
1225                   ($this->shuffle[$pc1map[($l >>  8) & 0xFF]] & "\x04\x04\x04\x04\x04\x04\x04\x00") |
1226                   ($this->shuffle[$pc1map[($l >> 16) & 0xFF]] & "\x02\x02\x02\x02\x02\x02\x02\x00") |
1227                   ($this->shuffle[$pc1map[($l >> 24) & 0xFF]] & "\x01\x01\x01\x01\x01\x01\x01\x00");
1228            $key = unpack('Nc/Nd', $key);
1229            $c = ( $key['c'] >> 4) & 0x0FFFFFFF;
1230            $d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F);
1231
1232            $keys[$des_round] = array(
1233                self::ENCRYPT => array(),
1234                self::DECRYPT => array_fill(0, 32, 0)
1235            );
1236            for ($i = 0, $ki = 31; $i < 16; ++$i, $ki-= 2) {
1237                $c <<= $shifts[$i];
1238                $c = ($c | ($c >> 28)) & 0x0FFFFFFF;
1239                $d <<= $shifts[$i];
1240                $d = ($d | ($d >> 28)) & 0x0FFFFFFF;
1241
1242                // Perform the PC-2 transformation.
1243                $cp = $pc2mapc1[ $c >> 24        ] | $pc2mapc2[($c >> 16) & 0xFF] |
1244                      $pc2mapc3[($c >>  8) & 0xFF] | $pc2mapc4[ $c        & 0xFF];
1245                $dp = $pc2mapd1[ $d >> 24        ] | $pc2mapd2[($d >> 16) & 0xFF] |
1246                      $pc2mapd3[($d >>  8) & 0xFF] | $pc2mapd4[ $d        & 0xFF];
1247
1248                // Reorder: odd bytes/even bytes. Push the result in key schedule.
1249                $val1 = ( $cp        & 0xFF000000) | (($cp <<  8) & 0x00FF0000) |
1250                        (($dp >> 16) & 0x0000FF00) | (($dp >>  8) & 0x000000FF);
1251                $val2 = (($cp <<  8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) |
1252                        (($dp >>  8) & 0x0000FF00) | ( $dp        & 0x000000FF);
1253                $keys[$des_round][self::ENCRYPT][       ] = $val1;
1254                $keys[$des_round][self::DECRYPT][$ki - 1] = $val1;
1255                $keys[$des_round][self::ENCRYPT][       ] = $val2;
1256                $keys[$des_round][self::DECRYPT][$ki    ] = $val2;
1257            }
1258        }
1259
1260        switch ($this->des_rounds) {
1261            case 3: // 3DES keys
1262                $this->keys = array(
1263                    self::ENCRYPT => array_merge(
1264                        $keys[0][self::ENCRYPT],
1265                        $keys[1][self::DECRYPT],
1266                        $keys[2][self::ENCRYPT]
1267                    ),
1268                    self::DECRYPT => array_merge(
1269                        $keys[2][self::DECRYPT],
1270                        $keys[1][self::ENCRYPT],
1271                        $keys[0][self::DECRYPT]
1272                    )
1273                );
1274                break;
1275            // case 1: // DES keys
1276            default:
1277                $this->keys = array(
1278                    self::ENCRYPT => $keys[0][self::ENCRYPT],
1279                    self::DECRYPT => $keys[0][self::DECRYPT]
1280                );
1281        }
1282    }
1283
1284    /**
1285     * Setup the performance-optimized function for de/encrypt()
1286     *
1287     * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
1288     * @access private
1289     */
1290    function _setupInlineCrypt()
1291    {
1292        $lambda_functions =& self::_getLambdaFunctions();
1293
1294        // Engine configuration for:
1295        // -  DES ($des_rounds == 1) or
1296        // - 3DES ($des_rounds == 3)
1297        $des_rounds = $this->des_rounds;
1298
1299        // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
1300        // (Currently, for DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
1301        // (Currently, for TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
1302        // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
1303        $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
1304
1305        // Generation of a unique hash for our generated code
1306        $code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
1307        if ($gen_hi_opt_code) {
1308            // For hi-optimized code, we create for each combination of
1309            // $mode, $des_rounds and $this->key its own encrypt/decrypt function.
1310            // After max 10 hi-optimized functions, we create generic
1311            // (still very fast.. but not ultra) functions for each $mode/$des_rounds
1312            // Currently 2 * 5 generic functions will be then max. possible.
1313            $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
1314        }
1315
1316        // Is there a re-usable $lambda_functions in there? If not, we have to create it.
1317        if (!isset($lambda_functions[$code_hash])) {
1318            // Init code for both, encrypt and decrypt.
1319            $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
1320                if (!$sbox1) {
1321                    $sbox1 = array_map("intval", $self->sbox1);
1322                    $sbox2 = array_map("intval", $self->sbox2);
1323                    $sbox3 = array_map("intval", $self->sbox3);
1324                    $sbox4 = array_map("intval", $self->sbox4);
1325                    $sbox5 = array_map("intval", $self->sbox5);
1326                    $sbox6 = array_map("intval", $self->sbox6);
1327                    $sbox7 = array_map("intval", $self->sbox7);
1328                    $sbox8 = array_map("intval", $self->sbox8);'
1329                    /* Merge $shuffle with $[inv]ipmap */ . '
1330                    for ($i = 0; $i < 256; ++$i) {
1331                        $shuffleip[]    =  $self->shuffle[$self->ipmap[$i]];
1332                        $shuffleinvip[] =  $self->shuffle[$self->invipmap[$i]];
1333                    }
1334                }
1335            ';
1336
1337            switch (true) {
1338                case $gen_hi_opt_code:
1339                    // In Hi-optimized code mode, we use our [3]DES key schedule as hardcoded integers.
1340                    // No futher initialisation of the $keys schedule is necessary.
1341                    // That is the extra performance boost.
1342                    $k = array(
1343                        self::ENCRYPT => $this->keys[self::ENCRYPT],
1344                        self::DECRYPT => $this->keys[self::DECRYPT]
1345                    );
1346                    $init_encrypt = '';
1347                    $init_decrypt = '';
1348                    break;
1349                default:
1350                    // In generic optimized code mode, we have to use, as the best compromise [currently],
1351                    // our key schedule as $ke/$kd arrays. (with hardcoded indexes...)
1352                    $k = array(
1353                        self::ENCRYPT => array(),
1354                        self::DECRYPT => array()
1355                    );
1356                    for ($i = 0, $c = count($this->keys[self::ENCRYPT]); $i < $c; ++$i) {
1357                        $k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
1358                        $k[self::DECRYPT][$i] = '$kd[' . $i . ']';
1359                    }
1360                    $init_encrypt = '$ke = $self->keys[$self::ENCRYPT];';
1361                    $init_decrypt = '$kd = $self->keys[$self::DECRYPT];';
1362                    break;
1363            }
1364
1365            // Creating code for en- and decryption.
1366            $crypt_block = array();
1367            foreach (array(self::ENCRYPT, self::DECRYPT) as $c) {
1368                /* Do the initial IP permutation. */
1369                $crypt_block[$c] = '
1370                    $in = unpack("N*", $in);
1371                    $l  = $in[1];
1372                    $r  = $in[2];
1373                    $in = unpack("N*",
1374                        ($shuffleip[ $r        & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
1375                        ($shuffleip[($r >>  8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
1376                        ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
1377                        ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
1378                        ($shuffleip[ $l        & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
1379                        ($shuffleip[($l >>  8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
1380                        ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
1381                        ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01")
1382                    );
1383                    ' . /* Extract L0 and R0 */ '
1384                    $l = $in[1];
1385                    $r = $in[2];
1386                ';
1387
1388                $l = '$l';
1389                $r = '$r';
1390
1391                // Perform DES or 3DES.
1392                for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) {
1393                    // Perform the 16 steps.
1394                    for ($i = 0; $i < 16; ++$i) {
1395                        // start of "the Feistel (F) function" - see the following URL:
1396                        // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
1397                        // Merge key schedule.
1398                        $crypt_block[$c].= '
1399                            $b1 = ((' . $r . ' >>  3) & 0x1FFFFFFF)  ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
1400                            $b2 = ((' . $r . ' >> 31) & 0x00000001)  ^ (' . $r . ' <<  1) ^ ' . $k[$c][++$ki] . ';' .
1401                            /* S-box indexing. */
1402                            $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
1403                                     $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
1404                                     $sbox5[($b1 >>  8) & 0x3F] ^ $sbox6[($b2 >>  8) & 0x3F] ^
1405                                     $sbox7[ $b1        & 0x3F] ^ $sbox8[ $b2        & 0x3F] ^ ' . $l . ';
1406                        ';
1407                        // end of "the Feistel (F) function"
1408
1409                        // swap L & R
1410                        list($l, $r) = array($r, $l);
1411                    }
1412                    list($l, $r) = array($r, $l);
1413                }
1414
1415                // Perform the inverse IP permutation.
1416                $crypt_block[$c].= '$in =
1417                    ($shuffleinvip[($l >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
1418                    ($shuffleinvip[($r >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
1419                    ($shuffleinvip[($l >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
1420                    ($shuffleinvip[($r >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
1421                    ($shuffleinvip[($l >>  8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
1422                    ($shuffleinvip[($r >>  8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
1423                    ($shuffleinvip[ $l        & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
1424                    ($shuffleinvip[ $r        & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
1425                ';
1426            }
1427
1428            // Creates the inline-crypt function
1429            $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
1430                array(
1431                   'init_crypt'    => $init_crypt,
1432                   'init_encrypt'  => $init_encrypt,
1433                   'init_decrypt'  => $init_decrypt,
1434                   'encrypt_block' => $crypt_block[self::ENCRYPT],
1435                   'decrypt_block' => $crypt_block[self::DECRYPT]
1436                )
1437            );
1438        }
1439
1440        // Set the inline-crypt function as callback in: $this->inline_crypt
1441        $this->inline_crypt = $lambda_functions[$code_hash];
1442    }
1443}
1444