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