PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 3.1.13.4
JetBackup – Backup, Restore & Migrate v3.1.13.4
3.1.22.4 3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / 3rdparty / phpseclib3 / Crypt / Blowfish.php
backup / src / JetBackup / 3rdparty / phpseclib3 / Crypt Last commit date
Common 9 months ago DH 9 months ago DSA 9 months ago EC 9 months ago RSA 9 months ago .htaccess 9 months ago AES.php 9 months ago Blowfish.php 9 months ago ChaCha20.php 9 months ago DES.php 9 months ago DH.php 9 months ago DSA.php 9 months ago EC.php 9 months ago Hash.php 9 months ago PublicKeyLoader.php 9 months ago RC2.php 9 months ago RC4.php 9 months ago RSA.php 9 months ago Random.php 9 months ago Rijndael.php 9 months ago Salsa20.php 9 months ago TripleDES.php 9 months ago Twofish.php 9 months ago index.html 9 months ago web.config 9 months ago
Blowfish.php
861 lines
1 <?php
2
3 /**
4 * Pure-PHP implementation of Blowfish.
5 *
6 * Uses an internal implementation.
7 *
8 * PHP version 5
9 *
10 * Useful resources are as follows:
11 *
12 * - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
13 *
14 * # An overview of bcrypt vs Blowfish
15 *
16 * OpenSSH private keys use a customized version of bcrypt. Specifically, instead of
17 * encrypting OrpheanBeholderScryDoubt 64 times OpenSSH's bcrypt variant encrypts
18 * OxychromaticBlowfishSwatDynamite 64 times. so we can't use crypt().
19 *
20 * bcrypt is basically Blowfish but instead of performing the key expansion once it performs
21 * the expansion 129 times for each round, with the first key expansion interleaving the salt
22 * and password. This renders OpenSSL unusable and forces us to use a pure-PHP implementation
23 * of blowfish.
24 *
25 * # phpseclib's three different _encryptBlock() implementations
26 *
27 * When using Blowfish as an encryption algorithm, _encryptBlock() is called 9 + 512 +
28 * (the number of blocks in the plaintext) times.
29 *
30 * Each of the first 9 calls to _encryptBlock() modify the P-array. Each of the next 512
31 * calls modify the S-boxes. The remaining _encryptBlock() calls operate on the plaintext to
32 * produce the ciphertext. In the pure-PHP implementation of Blowfish these remaining
33 * _encryptBlock() calls are highly optimized through the use of eval(). Among other things,
34 * P-array lookups are eliminated by hard-coding the key-dependent P-array values, and thus we
35 * have explained 2 of the 4 different _encryptBlock() implementations.
36 *
37 * With bcrypt things are a bit different. _encryptBlock() is called 1,079,296 times,
38 * assuming 16 rounds (which is what OpenSSH's bcrypt defaults to). The eval()-optimized
39 * _encryptBlock() isn't as beneficial because the P-array values are not constant. Well, they
40 * are constant, but only for, at most, 777 _encryptBlock() calls, which is equivalent to ~6KB
41 * of data. The average length of back to back _encryptBlock() calls with a fixed P-array is
42 * 514.12, which is ~4KB of data. Creating an eval()-optimized _encryptBlock() has an upfront
43 * cost, which is CPU dependent and is probably not going to be worth it for just ~4KB of
44 * data. Conseqeuently, bcrypt does not benefit from the eval()-optimized _encryptBlock().
45 *
46 * The regular _encryptBlock() does unpack() and pack() on every call, as well, and that can
47 * begin to add up after one million function calls.
48 *
49 * In theory, one might think that it might be beneficial to rewrite all block ciphers so
50 * that, instead of passing strings to _encryptBlock(), you convert the string to an array of
51 * integers and then pass successive subarrays of that array to _encryptBlock. This, however,
52 * kills PHP's memory use. Like let's say you have a 1MB long string. After doing
53 * $in = str_repeat('a', 1024 * 1024); PHP's memory utilization jumps up by ~1MB. After doing
54 * $blocks = str_split($in, 4); it jumps up by an additional ~16MB. After
55 * $blocks = array_map(fn($x) => unpack('N*', $x), $blocks); it jumps up by an additional
56 * ~90MB, yielding a 106x increase in memory usage. Consequently, it bcrypt calls a different
57 * _encryptBlock() then the regular Blowfish does. That said, the Blowfish _encryptBlock() is
58 * basically just a thin wrapper around the bcrypt _encryptBlock(), so there's that.
59 *
60 * # phpseclib's three different _setupKey() implementations
61 *
62 * Every bcrypt round is the equivalent of encrypting 512KB of data. Since OpenSSH uses 16
63 * rounds by default that's ~8MB of data that's essentially being encrypted whenever
64 * you use bcrypt. That's a lot of data, however, bcrypt operates within tighter constraints
65 * than regular Blowfish, so we can use that to our advantage. In particular, whereas Blowfish
66 * supports variable length keys, in bcrypt, the initial "key" is the sha512 hash of the
67 * password. sha512 hashes are 512 bits or 64 bytes long and thus the bcrypt keys are of a
68 * fixed length whereas Blowfish keys are not of a fixed length.
69 *
70 * bcrypt actually has two different key expansion steps. The first one (expandstate) is
71 * constantly XOR'ing every _encryptBlock() parameter against the salt prior _encryptBlock()'s
72 * being called. The second one (expand0state) is more similar to Blowfish's _setupKey()
73 * but it can still use the fixed length key optimization discussed above and can do away with
74 * the pack() / unpack() calls.
75 *
76 * I suppose _setupKey() could be made to be a thin wrapper around expandstate() but idk it's
77 * just a lot of work for very marginal benefits as _setupKey() is only called once for
78 * regular Blowfish vs the 128 times it's called --per round-- with bcrypt.
79 *
80 * # blowfish + bcrypt in the same class
81 *
82 * Altho there's a lot of Blowfish code that bcrypt doesn't re-use, bcrypt does re-use the
83 * initial S-boxes, the initial P-array and the int-only _encryptBlock() implementation.
84 *
85 * # Credit
86 *
87 * phpseclib's bcrypt implementation is based losely off of OpenSSH's implementation:
88 *
89 * https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bcrypt_pbkdf.c
90 *
91 * Here's a short example of how to use this library:
92 * <code>
93 * <?php
94 * include 'vendor/autoload.php';
95 *
96 * $blowfish = new \phpseclib3\Crypt\Blowfish('ctr');
97 *
98 * $blowfish->setKey('12345678901234567890123456789012');
99 *
100 * $plaintext = str_repeat('a', 1024);
101 *
102 * echo $blowfish->decrypt($blowfish->encrypt($plaintext));
103 * ?>
104 * </code>
105 *
106 * @author Jim Wigginton <terrafrost@php.net>
107 * @author Hans-Juergen Petrich <petrich@tronic-media.com>
108 * @copyright 2007 Jim Wigginton
109 * @license http://www.opensource.org/licenses/mit-license.html MIT License
110 * @link http://phpseclib.sourceforge.net
111 */
112
113 declare(strict_types=1);
114
115 namespace phpseclib3\Crypt;
116
117 use phpseclib3\Crypt\Common\BlockCipher;
118 use phpseclib3\Exception\InvalidArgumentException;
119 use phpseclib3\Exception\LengthException;
120
121 /**
122 * Pure-PHP implementation of Blowfish.
123 *
124 * @author Jim Wigginton <terrafrost@php.net>
125 * @author Hans-Juergen Petrich <petrich@tronic-media.com>
126 */
127 class Blowfish extends BlockCipher
128 {
129 /**
130 * Block Length of the cipher
131 *
132 * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
133 * @var int
134 */
135 protected $block_size = 8;
136
137 /**
138 * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
139 *
140 * S-Box 0
141 *
142 * @var array
143 */
144 private static $sbox0 = [
145 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
146 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
147 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
148 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
149 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
150 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
151 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
152 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
153 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
154 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
155 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
156 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
157 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
158 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
159 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
160 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
161 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
162 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
163 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
164 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
165 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
166 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
167 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
168 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
169 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
170 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
171 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
172 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
173 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
174 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
175 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
176 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
177 ];
178
179 /**
180 * S-Box 1
181 *
182 * @var array
183 */
184 private static $sbox1 = [
185 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
186 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
187 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
188 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
189 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
190 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
191 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
192 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
193 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
194 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
195 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
196 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
197 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
198 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
199 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
200 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
201 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
202 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
203 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
204 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
205 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
206 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
207 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
208 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
209 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
210 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
211 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
212 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
213 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
214 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
215 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
216 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
217 ];
218
219 /**
220 * S-Box 2
221 *
222 * @var array
223 */
224 private static $sbox2 = [
225 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
226 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
227 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
228 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
229 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
230 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
231 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
232 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
233 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
234 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
235 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
236 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
237 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
238 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
239 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
240 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
241 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
242 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
243 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
244 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
245 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
246 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
247 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
248 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
249 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
250 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
251 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
252 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
253 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
254 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
255 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
256 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
257 ];
258
259 /**
260 * S-Box 3
261 *
262 * @var array
263 */
264 private static $sbox3 = [
265 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
266 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
267 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
268 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
269 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
270 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
271 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
272 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
273 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
274 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
275 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
276 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
277 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
278 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
279 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
280 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
281 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
282 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
283 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
284 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
285 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
286 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
287 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
288 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
289 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
290 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
291 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
292 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
293 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
294 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
295 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
296 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
297 ];
298
299 /**
300 * P-Array consists of 18 32-bit subkeys
301 *
302 * @var array
303 */
304 private static $parray = [
305 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
306 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
307 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
308 ];
309
310 /**
311 * The BCTX-working Array
312 *
313 * Holds the expanded key [p] and the key-depended s-boxes [sb]
314 *
315 * @var array
316 */
317 private $bctx;
318
319 /**
320 * Holds the last used key
321 *
322 * @var array
323 */
324 private $kl;
325
326 /**
327 * The Key Length (in bytes)
328 * {@internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
329 * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
330 * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
331 * of that, we'll just precompute it once.}
332 *
333 * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength()
334 * @var int
335 */
336 protected $key_length = 16;
337
338 /**
339 * Default Constructor.
340 *
341 * @throws InvalidArgumentException if an invalid / unsupported mode is provided
342 */
343 public function __construct(string $mode)
344 {
345 parent::__construct($mode);
346
347 if ($this->mode == self::MODE_STREAM) {
348 throw new InvalidArgumentException('Block ciphers cannot be ran in stream mode');
349 }
350 }
351
352 /**
353 * Sets the key length.
354 *
355 * Key lengths can be between 32 and 448 bits.
356 */
357 public function setKeyLength(int $length): void
358 {
359 if ($length < 32 || $length > 448) {
360 throw new LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes between 32 and 448 bits are supported');
361 }
362
363 $this->key_length = $length >> 3;
364
365 parent::setKeyLength($length);
366 }
367
368 /**
369 * Test for engine validity
370 *
371 * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
372 *
373 * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
374 */
375 protected function isValidEngineHelper(int $engine): bool
376 {
377 if ($engine == self::ENGINE_OPENSSL) {
378 if ($this->key_length < 16) {
379 return false;
380 }
381 // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1
382 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider"
383 // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not
384 if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
385 return false;
386 }
387 $this->cipher_name_openssl_ecb = 'bf-ecb';
388 $this->cipher_name_openssl = 'bf-' . $this->openssl_translate_mode();
389 }
390
391 return parent::isValidEngineHelper($engine);
392 }
393
394 /**
395 * Setup the key (expansion)
396 *
397 * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
398 */
399 protected function setupKey(): void
400 {
401 if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
402 // already expanded
403 return;
404 }
405 $this->kl = ['key' => $this->key];
406
407 /* key-expanding p[] and S-Box building sb[] */
408 $this->bctx = [
409 'p' => [],
410 'sb' => [
411 self::$sbox0,
412 self::$sbox1,
413 self::$sbox2,
414 self::$sbox3,
415 ],
416 ];
417
418 // unpack binary string in unsigned chars
419 $key = array_values(unpack('C*', $this->key));
420 $keyl = count($key);
421 // with bcrypt $keyl will always be 16 (because the key is the sha512 of the key you provide)
422 for ($j = 0, $i = 0; $i < 18; ++$i) {
423 // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
424 for ($data = 0, $k = 0; $k < 4; ++$k) {
425 $data = ($data << 8) | $key[$j];
426 if (++$j >= $keyl) {
427 $j = 0;
428 }
429 }
430 $this->bctx['p'][] = self::$parray[$i] ^ intval($data);
431 }
432
433 // encrypt the zero-string, replace P1 and P2 with the encrypted data,
434 // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
435 $data = "\0\0\0\0\0\0\0\0";
436 for ($i = 0; $i < 18; $i += 2) {
437 [$l, $r] = array_values(unpack('N*', $data = $this->encryptBlock($data)));
438 $this->bctx['p'][$i ] = $l;
439 $this->bctx['p'][$i + 1] = $r;
440 }
441 for ($i = 0; $i < 4; ++$i) {
442 for ($j = 0; $j < 256; $j += 2) {
443 [$l, $r] = array_values(unpack('N*', $data = $this->encryptBlock($data)));
444 $this->bctx['sb'][$i][$j ] = $l;
445 $this->bctx['sb'][$i][$j + 1] = $r;
446 }
447 }
448 }
449
450 /**
451 * Initialize Static Variables
452 */
453 protected static function initialize_static_variables(): void
454 {
455 if (is_float(self::$sbox2[0])) {
456 self::$sbox0 = array_map('intval', self::$sbox0);
457 self::$sbox1 = array_map('intval', self::$sbox1);
458 self::$sbox2 = array_map('intval', self::$sbox2);
459 self::$sbox3 = array_map('intval', self::$sbox3);
460 self::$parray = array_map('intval', self::$parray);
461 }
462
463 parent::initialize_static_variables();
464 }
465
466 /**
467 * bcrypt
468 */
469 private static function bcrypt_hash(string $sha2pass, string $sha2salt): string
470 {
471 $p = self::$parray;
472 $sbox0 = self::$sbox0;
473 $sbox1 = self::$sbox1;
474 $sbox2 = self::$sbox2;
475 $sbox3 = self::$sbox3;
476
477 $cdata = array_values(unpack('N*', 'OxychromaticBlowfishSwatDynamite'));
478 $sha2pass = array_values(unpack('N*', $sha2pass));
479 $sha2salt = array_values(unpack('N*', $sha2salt));
480
481 self::expandstate($sha2salt, $sha2pass, $sbox0, $sbox1, $sbox2, $sbox3, $p);
482 for ($i = 0; $i < 64; $i++) {
483 self::expand0state($sha2salt, $sbox0, $sbox1, $sbox2, $sbox3, $p);
484 self::expand0state($sha2pass, $sbox0, $sbox1, $sbox2, $sbox3, $p);
485 }
486
487 for ($i = 0; $i < 64; $i++) {
488 for ($j = 0; $j < 8; $j += 2) { // count($cdata) == 8
489 [$cdata[$j], $cdata[$j + 1]] = self::encryptBlockHelperFast($cdata[$j], $cdata[$j + 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
490 }
491 }
492
493 return pack('L*', ...$cdata);
494 }
495
496 /**
497 * Performs OpenSSH-style bcrypt
498 */
499 public static function bcrypt_pbkdf(string $pass, string $salt, int $keylen, int $rounds): string
500 {
501 self::initialize_static_variables();
502
503 if (PHP_INT_SIZE == 4) {
504 throw new \RuntimeException('bcrypt is far too slow to be practical on 32-bit versions of PHP');
505 }
506
507 $sha2pass = hash('sha512', $pass, true);
508 $results = [];
509 $count = 1;
510 while (32 * count($results) < $keylen) {
511 $countsalt = $salt . pack('N', $count++);
512 $sha2salt = hash('sha512', $countsalt, true);
513 $out = $tmpout = self::bcrypt_hash($sha2pass, $sha2salt);
514 for ($i = 1; $i < $rounds; $i++) {
515 $sha2salt = hash('sha512', $tmpout, true);
516 $tmpout = self::bcrypt_hash($sha2pass, $sha2salt);
517 $out ^= $tmpout;
518 }
519 $results[] = $out;
520 }
521 $output = '';
522 for ($i = 0; $i < 32; $i++) {
523 foreach ($results as $result) {
524 $output .= $result[$i];
525 }
526 }
527 return substr($output, 0, $keylen);
528 }
529
530 /**
531 * Key expansion without salt
532 *
533 * @access private
534 * @param int[] $key
535 * @param int[] $sbox0
536 * @param int[] $sbox1
537 * @param int[] $sbox2
538 * @param int[] $sbox3
539 * @param int[] $p
540 * @see self::_bcrypt_hash()
541 */
542 private static function expand0state(array $key, array &$sbox0, array &$sbox1, array &$sbox2, array &$sbox3, array &$p): void
543 {
544 // expand0state is basically the same thing as this:
545 //return self::expandstate(array_fill(0, 16, 0), $key);
546 // but this separate function eliminates a bunch of XORs and array lookups
547
548 $p = [
549 $p[0] ^ $key[0],
550 $p[1] ^ $key[1],
551 $p[2] ^ $key[2],
552 $p[3] ^ $key[3],
553 $p[4] ^ $key[4],
554 $p[5] ^ $key[5],
555 $p[6] ^ $key[6],
556 $p[7] ^ $key[7],
557 $p[8] ^ $key[8],
558 $p[9] ^ $key[9],
559 $p[10] ^ $key[10],
560 $p[11] ^ $key[11],
561 $p[12] ^ $key[12],
562 $p[13] ^ $key[13],
563 $p[14] ^ $key[14],
564 $p[15] ^ $key[15],
565 $p[16] ^ $key[0],
566 $p[17] ^ $key[1],
567 ];
568
569 [$p[0], $p[1]] = self::encryptBlockHelperFast(0, 0, $sbox0, $sbox1, $sbox2, $sbox3, $p);
570 for ($i = 2; $i < 18; $i += 2) {
571 [$p[$i], $p[$i + 1]] = self::encryptBlockHelperFast($p[$i - 2], $p[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
572 }
573
574 [$sbox0[0], $sbox0[1]] = self::encryptBlockHelperFast($p[16], $p[17], $sbox0, $sbox1, $sbox2, $sbox3, $p);
575 for ($i = 2; $i < 256; $i += 2) {
576 [$sbox0[$i], $sbox0[$i + 1]] = self::encryptBlockHelperFast($sbox0[$i - 2], $sbox0[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
577 }
578
579 [$sbox1[0], $sbox1[1]] = self::encryptBlockHelperFast($sbox0[254], $sbox0[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
580 for ($i = 2; $i < 256; $i += 2) {
581 [$sbox1[$i], $sbox1[$i + 1]] = self::encryptBlockHelperFast($sbox1[$i - 2], $sbox1[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
582 }
583
584 [$sbox2[0], $sbox2[1]] = self::encryptBlockHelperFast($sbox1[254], $sbox1[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
585 for ($i = 2; $i < 256; $i += 2) {
586 [$sbox2[$i], $sbox2[$i + 1]] = self::encryptBlockHelperFast($sbox2[$i - 2], $sbox2[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
587 }
588
589 [$sbox3[0], $sbox3[1]] = self::encryptBlockHelperFast($sbox2[254], $sbox2[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
590 for ($i = 2; $i < 256; $i += 2) {
591 [$sbox3[$i], $sbox3[$i + 1]] = self::encryptBlockHelperFast($sbox3[$i - 2], $sbox3[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
592 }
593 }
594
595 /**
596 * Key expansion with salt
597 *
598 * @access private
599 * @param int[] $data
600 * @param int[] $key
601 * @param int[] $sbox0
602 * @param int[] $sbox1
603 * @param int[] $sbox2
604 * @param int[] $sbox3
605 * @param int[] $p
606 * @see self::_bcrypt_hash()
607 */
608 private static function expandstate(array $data, array $key, array &$sbox0, array &$sbox1, array &$sbox2, array &$sbox3, array &$p): void
609 {
610 $p = [
611 $p[0] ^ $key[0],
612 $p[1] ^ $key[1],
613 $p[2] ^ $key[2],
614 $p[3] ^ $key[3],
615 $p[4] ^ $key[4],
616 $p[5] ^ $key[5],
617 $p[6] ^ $key[6],
618 $p[7] ^ $key[7],
619 $p[8] ^ $key[8],
620 $p[9] ^ $key[9],
621 $p[10] ^ $key[10],
622 $p[11] ^ $key[11],
623 $p[12] ^ $key[12],
624 $p[13] ^ $key[13],
625 $p[14] ^ $key[14],
626 $p[15] ^ $key[15],
627 $p[16] ^ $key[0],
628 $p[17] ^ $key[1],
629 ];
630
631 [$p[0], $p[1]] = self::encryptBlockHelperFast($data[0], $data[1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
632 for ($i = 2, $j = 2; $i < 18; $i += 2, $j = ($j + 2) % 16) {
633 [$p[$i], $p[$i + 1]] = self::encryptBlockHelperFast($data[$j] ^ $p[$i - 2], $data[$j + 1] ^ $p[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
634 }
635
636 [$sbox0[0], $sbox0[1]] = self::encryptBlockHelperFast($data[2] ^ $p[16], $data[3] ^ $p[17], $sbox0, $sbox1, $sbox2, $sbox3, $p);
637 for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) { // instead of 16 maybe count($data) would be better?
638 [$sbox0[$i], $sbox0[$i + 1]] = self::encryptBlockHelperFast($data[$j] ^ $sbox0[$i - 2], $data[$j + 1] ^ $sbox0[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
639 }
640
641 [$sbox1[0], $sbox1[1]] = self::encryptBlockHelperFast($data[2] ^ $sbox0[254], $data[3] ^ $sbox0[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
642 for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) {
643 [$sbox1[$i], $sbox1[$i + 1]] = self::encryptBlockHelperFast($data[$j] ^ $sbox1[$i - 2], $data[$j + 1] ^ $sbox1[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
644 }
645
646 [$sbox2[0], $sbox2[1]] = self::encryptBlockHelperFast($data[2] ^ $sbox1[254], $data[3] ^ $sbox1[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
647 for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) {
648 [$sbox2[$i], $sbox2[$i + 1]] = self::encryptBlockHelperFast($data[$j] ^ $sbox2[$i - 2], $data[$j + 1] ^ $sbox2[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
649 }
650
651 [$sbox3[0], $sbox3[1]] = self::encryptBlockHelperFast($data[2] ^ $sbox2[254], $data[3] ^ $sbox2[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
652 for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) {
653 [$sbox3[$i], $sbox3[$i + 1]] = self::encryptBlockHelperFast($data[$j] ^ $sbox3[$i - 2], $data[$j + 1] ^ $sbox3[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
654 }
655 }
656
657 /**
658 * Encrypts a block
659 */
660 protected function encryptBlock(string $in): string
661 {
662 $p = $this->bctx['p'];
663 // extract($this->bctx['sb'], EXTR_PREFIX_ALL, 'sb'); // slower
664 $sb_0 = $this->bctx['sb'][0];
665 $sb_1 = $this->bctx['sb'][1];
666 $sb_2 = $this->bctx['sb'][2];
667 $sb_3 = $this->bctx['sb'][3];
668
669 $in = unpack('N*', $in);
670 $l = $in[1];
671 $r = $in[2];
672
673 [$r, $l] = PHP_INT_SIZE == 4 ?
674 self::encryptBlockHelperSlow($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p) :
675 self::encryptBlockHelperFast($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p);
676
677 return pack("N*", $r, $l);
678 }
679
680 /**
681 * Fast helper function for block encryption
682 *
683 * @access private
684 * @param int[] $sbox0
685 * @param int[] $sbox1
686 * @param int[] $sbox2
687 * @param int[] $sbox3
688 * @param int[] $p
689 * @return int[]
690 */
691 private static function encryptBlockHelperFast(int $x0, int $x1, array $sbox0, array $sbox1, array $sbox2, array $sbox3, array $p): array
692 {
693 $x0 ^= $p[0];
694 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1];
695 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2];
696 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3];
697 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4];
698 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5];
699 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6];
700 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7];
701 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8];
702 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9];
703 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10];
704 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11];
705 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12];
706 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13];
707 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14];
708 $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15];
709 $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16];
710
711 return [$x1 & 0xFFFFFFFF ^ $p[17], $x0 & 0xFFFFFFFF];
712 }
713
714 /**
715 * Slow helper function for block encryption
716 *
717 * @access private
718 * @param int[] $sbox0
719 * @param int[] $sbox1
720 * @param int[] $sbox2
721 * @param int[] $sbox3
722 * @param int[] $p
723 * @return int[]
724 */
725 private static function encryptBlockHelperSlow(int $x0, int $x1, array $sbox0, array $sbox1, array $sbox2, array $sbox3, array $p): array
726 {
727 // -16777216 == intval(0xFF000000) on 32-bit PHP installs
728 $x0 ^= $p[0];
729 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1];
730 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2];
731 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3];
732 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4];
733 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5];
734 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6];
735 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7];
736 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8];
737 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9];
738 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10];
739 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11];
740 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12];
741 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13];
742 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14];
743 $x1 ^= intval((intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15];
744 $x0 ^= intval((intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16];
745
746 return [$x1 ^ $p[17], $x0];
747 }
748
749 /**
750 * Decrypts a block
751 */
752 protected function decryptBlock(string $in): string
753 {
754 $p = $this->bctx['p'];
755 $sb_0 = $this->bctx['sb'][0];
756 $sb_1 = $this->bctx['sb'][1];
757 $sb_2 = $this->bctx['sb'][2];
758 $sb_3 = $this->bctx['sb'][3];
759
760 $in = unpack('N*', $in);
761 $l = $in[1];
762 $r = $in[2];
763
764 for ($i = 17; $i > 2; $i -= 2) {
765 $l ^= $p[$i];
766 $r ^= intval((intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
767 $sb_2[$l >> 8 & 0xff]) +
768 $sb_3[$l & 0xff]);
769
770 $r ^= $p[$i - 1];
771 $l ^= intval((intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
772 $sb_2[$r >> 8 & 0xff]) +
773 $sb_3[$r & 0xff]);
774 }
775 return pack('N*', $r ^ $p[0], $l ^ $p[1]);
776 }
777
778 /**
779 * Setup the performance-optimized function for de/encrypt()
780 *
781 * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
782 */
783 protected function setupInlineCrypt(): void
784 {
785 $p = $this->bctx['p'];
786 $init_crypt = '
787 static $sb_0, $sb_1, $sb_2, $sb_3;
788 if (!$sb_0) {
789 $sb_0 = $this->bctx["sb"][0];
790 $sb_1 = $this->bctx["sb"][1];
791 $sb_2 = $this->bctx["sb"][2];
792 $sb_3 = $this->bctx["sb"][3];
793 }
794 ';
795
796 // Generating encrypt code:
797 $encrypt_block = '
798 $in = unpack("N*", $in);
799 $l = $in[1];
800 $r = $in[2];
801 ';
802 for ($i = 0; $i < 16; $i += 2) {
803 $encrypt_block .= '
804 $l^= ' . $p[$i] . ';
805 $r^= intval((intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
806 $sb_2[$l >> 8 & 0xff]) +
807 $sb_3[$l & 0xff]);
808
809 $r^= ' . $p[$i + 1] . ';
810 $l^= intval((intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
811 $sb_2[$r >> 8 & 0xff]) +
812 $sb_3[$r & 0xff]);
813 ';
814 }
815 $encrypt_block .= '
816 $in = pack("N*",
817 $r ^ ' . $p[17] . ',
818 $l ^ ' . $p[16] . '
819 );
820 ';
821
822 // Generating decrypt code:
823 $decrypt_block = '
824 $in = unpack("N*", $in);
825 $l = $in[1];
826 $r = $in[2];
827 ';
828
829 for ($i = 17; $i > 2; $i -= 2) {
830 $decrypt_block .= '
831 $l^= ' . $p[$i] . ';
832 $r^= intval((intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
833 $sb_2[$l >> 8 & 0xff]) +
834 $sb_3[$l & 0xff]);
835
836 $r^= ' . $p[$i - 1] . ';
837 $l^= intval((intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
838 $sb_2[$r >> 8 & 0xff]) +
839 $sb_3[$r & 0xff]);
840 ';
841 }
842
843 $decrypt_block .= '
844 $in = pack("N*",
845 $r ^ ' . $p[0] . ',
846 $l ^ ' . $p[1] . '
847 );
848 ';
849
850 $this->inline_crypt = $this->createInlineCryptFunction(
851 [
852 'init_crypt' => $init_crypt,
853 'init_encrypt' => '',
854 'init_decrypt' => '',
855 'encrypt_block' => $encrypt_block,
856 'decrypt_block' => $decrypt_block,
857 ]
858 );
859 }
860 }
861