mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-26 19:40:28 +00:00
Merge branch 'bcrypt' into bcrypt2
This commit is contained in:
commit
11977eeb3c
@ -500,6 +500,53 @@ abstract class Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->_setEngine();
|
$this->_setEngine();
|
||||||
|
|
||||||
|
// Determining whether inline crypting can be used by the cipher
|
||||||
|
if ($this->use_inline_crypt !== false) {
|
||||||
|
$this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined('CRYPT_BASE_USE_SAFE_INTVAL')) {
|
||||||
|
switch (true) {
|
||||||
|
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
|
||||||
|
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
|
||||||
|
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
||||||
|
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
|
||||||
|
define('CRYPT_BASE_USE_SAFE_INTVAL', true);
|
||||||
|
break;
|
||||||
|
case (php_uname('m') & "\xDF\xDF\xDF") == 'ARM':
|
||||||
|
switch (true) {
|
||||||
|
/* PHP 7.0.0 introduced a bug that affected 32-bit ARM processors:
|
||||||
|
|
||||||
|
https://github.com/php/php-src/commit/716da71446ebbd40fa6cf2cea8a4b70f504cc3cd
|
||||||
|
|
||||||
|
altho the changelogs make no mention of it, this bug was fixed with this commit:
|
||||||
|
|
||||||
|
https://github.com/php/php-src/commit/c1729272b17a1fe893d1a54e423d3b71470f3ee8
|
||||||
|
|
||||||
|
affected versions of PHP are: 7.0.x, 7.1.0 - 7.1.23 and 7.2.0 - 7.2.11 */
|
||||||
|
case PHP_VERSION_ID >= 70000 && PHP_VERSION_ID <= 70123:
|
||||||
|
case PHP_VERSION_ID >= 70200 && PHP_VERSION_ID <= 70211:
|
||||||
|
define('CRYPT_BASE_USE_SAFE_INTVAL', true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
define('CRYPT_BASE_USE_SAFE_INTVAL', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHP4 compatible Default Constructor.
|
||||||
|
*
|
||||||
|
* @see self::__construct()
|
||||||
|
* @param int $mode
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Crypt_Base($mode = CRYPT_MODE_CBC)
|
||||||
|
{
|
||||||
|
$this->__construct($mode);
|
||||||
|
>>>>>>> bcrypt
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -593,6 +640,10 @@ abstract class Base
|
|||||||
* $hash, $salt, $count, $dkLen
|
* $hash, $salt, $count, $dkLen
|
||||||
*
|
*
|
||||||
* Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
|
* Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
|
||||||
|
* {@link https://en.wikipedia.org/wiki/Bcrypt bcypt}:
|
||||||
|
* $salt, $rounds, $keylen
|
||||||
|
*
|
||||||
|
* This is a modified version of bcrypt used by OpenSSH.
|
||||||
*
|
*
|
||||||
* @see Crypt/Hash.php
|
* @see Crypt/Hash.php
|
||||||
* @param string $password
|
* @param string $password
|
||||||
@ -606,6 +657,32 @@ abstract class Base
|
|||||||
$key = '';
|
$key = '';
|
||||||
|
|
||||||
switch ($method) {
|
switch ($method) {
|
||||||
|
case 'bcrypt':
|
||||||
|
if (!class_exists('Crypt_Blowfish')) {
|
||||||
|
include_once 'Crypt/Blowfish.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
$func_args = func_get_args();
|
||||||
|
|
||||||
|
if (!isset($func_args[2])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$salt = $func_args[2];
|
||||||
|
|
||||||
|
$rounds = isset($func_args[3]) ? $func_args[3] : 16;
|
||||||
|
$keylen = isset($func_args[4]) ? $func_args[4] : $this->key_length;
|
||||||
|
|
||||||
|
$bf = new Crypt_Blowfish();
|
||||||
|
$key = $bf->bcrypt_pbkdf($password, $salt, $keylen + $this->block_size, $rounds);
|
||||||
|
if (!$key) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setKey(substr($key, 0, $keylen));
|
||||||
|
$this->setIV(substr($key, $keylen));
|
||||||
|
|
||||||
|
return true;
|
||||||
default: // 'pbkdf2' or 'pbkdf1'
|
default: // 'pbkdf2' or 'pbkdf1'
|
||||||
$func_args = func_get_args();
|
$func_args = func_get_args();
|
||||||
|
|
||||||
@ -2798,27 +2875,8 @@ abstract class Base
|
|||||||
*/
|
*/
|
||||||
function safe_intval($x)
|
function safe_intval($x)
|
||||||
{
|
{
|
||||||
switch (true) {
|
if (CRYPT_BASE_USE_SAFE_INTVAL || is_int($x)) {
|
||||||
case is_int($x):
|
return $x;
|
||||||
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
|
||||||
return $x;
|
|
||||||
case (php_uname('m') & "\xDF\xDF\xDF") == 'ARM':
|
|
||||||
switch (true) {
|
|
||||||
/* PHP 7.0.0 introduced a bug that affected 32-bit ARM processors:
|
|
||||||
|
|
||||||
https://github.com/php/php-src/commit/716da71446ebbd40fa6cf2cea8a4b70f504cc3cd
|
|
||||||
|
|
||||||
altho the changelogs make no mention of it, this bug was fixed with this commit:
|
|
||||||
|
|
||||||
https://github.com/php/php-src/commit/c1729272b17a1fe893d1a54e423d3b71470f3ee8
|
|
||||||
|
|
||||||
affected versions of PHP are: 7.0.x, 7.1.0 - 7.1.23 and 7.2.0 - 7.2.11 */
|
|
||||||
case PHP_VERSION_ID >= 70000 && PHP_VERSION_ID <= 70123:
|
|
||||||
case PHP_VERSION_ID >= 70200 && PHP_VERSION_ID <= 70211:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return $x;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
|
return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
|
||||||
((fmod(floor($x / 0x80000000), 2) & 1) << 31);
|
((fmod(floor($x / 0x80000000), 2) & 1) << 31);
|
||||||
@ -2832,23 +2890,12 @@ abstract class Base
|
|||||||
*/
|
*/
|
||||||
function safe_intval_inline()
|
function safe_intval_inline()
|
||||||
{
|
{
|
||||||
switch (true) {
|
if (CRYPT_BASE_USE_SAFE_INTVAL) {
|
||||||
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
|
return '%s';
|
||||||
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
|
||||||
return '%s';
|
|
||||||
break;
|
|
||||||
case (php_uname('m') & "\xDF\xDF\xDF") == 'ARM':
|
|
||||||
switch (true) {
|
|
||||||
case PHP_VERSION_ID >= 70000 && PHP_VERSION_ID <= 70123:
|
|
||||||
case PHP_VERSION_ID >= 70200 && PHP_VERSION_ID <= 70211:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return '%s';
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
$safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
|
|
||||||
return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
|
||||||
|
return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,87 @@
|
|||||||
*
|
*
|
||||||
* - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
|
* - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
|
||||||
*
|
*
|
||||||
|
* # An overview of bcrypt vs Blowfish
|
||||||
|
*
|
||||||
|
* OpenSSH private keys use a customized version of bcrypt. Specifically, instead of
|
||||||
|
* encrypting OrpheanBeholderScryDoubt 64 times OpenSSH's bcrypt variant encrypts
|
||||||
|
* OxychromaticBlowfishSwatDynamite 64 times. so we can't use crypt().
|
||||||
|
*
|
||||||
|
* bcrypt is basically Blowfish but instead of performing the key expansion once it performs
|
||||||
|
* the expansion 129 times for each round, with the first key expansion interleaving the salt
|
||||||
|
* and password. This renders OpenSSL unusable and forces us to use a pure-PHP implementation
|
||||||
|
* of blowfish.
|
||||||
|
*
|
||||||
|
* # phpseclib's four different _encryptBlock() implementations
|
||||||
|
*
|
||||||
|
* When using Blowfish as an encryption algorithm, _encryptBlock() is called 9 + 512 +
|
||||||
|
* (the number of blocks in the plaintext) times.
|
||||||
|
*
|
||||||
|
* Each of the first 9 calls to _encryptBlock() modify the P-array. Each of the next 512
|
||||||
|
* calls modify the S-boxes. The remaining _encryptBlock() calls operate on the plaintext to
|
||||||
|
* produce the ciphertext. In the pure-PHP implementation of Blowfish these remaining
|
||||||
|
* _encryptBlock() calls are highly optimized through the use of eval(). Among other things,
|
||||||
|
* P-array lookups are eliminated by hard-coding the key-dependent P-array values, and thus we
|
||||||
|
* have explained 2 of the 4 different _encryptBlock() implementations.
|
||||||
|
*
|
||||||
|
* With bcrypt things are a bit different. _encryptBlock() is called 1,079,296 times,
|
||||||
|
* assuming 16 rounds (which is what OpenSSH's bcrypt defaults to). The eval()-optimized
|
||||||
|
* _encryptBlock() isn't as beneficial because the P-array values are not constant. Well, they
|
||||||
|
* are constant, but only for, at most, 777 _encryptBlock() calls, which is equivalent to ~6KB
|
||||||
|
* of data. The average length of back to back _encryptBlock() calls with a fixed P-array is
|
||||||
|
* 514.12, which is ~4KB of data. Creating an eval()-optimized _encryptBlock() has an upfront
|
||||||
|
* cost, which is CPU dependent and is probably not going to be worth it for just ~4KB of
|
||||||
|
* data. Conseqeuently, bcrypt does not benefit from the eval()-optimized _encryptBlock().
|
||||||
|
*
|
||||||
|
* The regular _encryptBlock() does unpack() and pack() on every call, as well, and that can
|
||||||
|
* begin to add up after one million function calls.
|
||||||
|
*
|
||||||
|
* In theory, one might think that it might be beneficial to rewrite all block ciphers so
|
||||||
|
* that, instead of passing strings to _encryptBlock(), you convert the string to an array of
|
||||||
|
* integers and then pass successive subarrays of that array to _encryptBlock. This, however,
|
||||||
|
* kills PHP's memory use. Like let's say you have a 1MB long string. After doing
|
||||||
|
* $in = str_repeat('a', 1024 * 1024); PHP's memory utilization jumps up by ~1MB. After doing
|
||||||
|
* $blocks = str_split($in, 4); it jumps up by an additional ~16MB. After
|
||||||
|
* $blocks = array_map(fn($x) => unpack('N*', $x), $blocks); it jumps up by an additional
|
||||||
|
* ~90MB, yielding a 106x increase in memory usage. Consequently, it bcrypt calls a different
|
||||||
|
* _encryptBlock() then the regular Blowfish does. That said, the Blowfish _encryptBlock() is
|
||||||
|
* basically just a thin wrapper around the bcrypt _encryptBlock(), so there's that.
|
||||||
|
*
|
||||||
|
* This explains 3 of the 4 _encryptBlock() implementations. the last _encryptBlock()
|
||||||
|
* implementation can best be understood by doing Ctrl + F and searching for where
|
||||||
|
* CRYPT_BASE_USE_SAFE_INTVAL is defined.
|
||||||
|
*
|
||||||
|
* # phpseclib's three different _setupKey() implementations
|
||||||
|
*
|
||||||
|
* Every bcrypt round is the equivalent of encrypting 512KB of data. Since OpenSSH uses 16
|
||||||
|
* rounds by default that's ~8MB of data that's essentially being encrypted whenever
|
||||||
|
* you use bcrypt. That's a lot of data, however, bcrypt operates within tighter constraints
|
||||||
|
* than regular Blowfish, so we can use that to our advantage. In particular, whereas Blowfish
|
||||||
|
* supports variable length keys, in bcrypt, the initial "key" is the sha512 hash of the
|
||||||
|
* password. sha512 hashes are 512 bits or 64 bytes long and thus the bcrypt keys are of a
|
||||||
|
* fixed length whereas Blowfish keys are not of a fixed length.
|
||||||
|
*
|
||||||
|
* bcrypt actually has two different key expansion steps. The first one (expandstate) is
|
||||||
|
* constantly XOR'ing every _encryptBlock() parameter against the salt prior _encryptBlock()'s
|
||||||
|
* being called. The second one (expand0state) is more similar to Blowfish's _setupKey()
|
||||||
|
* but it can still use the fixed length key optimization discussed above and can do away with
|
||||||
|
* the pack() / unpack() calls.
|
||||||
|
*
|
||||||
|
* I suppose _setupKey() could be made to be a thin wrapper around expandstate() but idk it's
|
||||||
|
* just a lot of work for very marginal benefits as _setupKey() is only called once for
|
||||||
|
* regular Blowfish vs the 128 times it's called --per round-- with bcrypt.
|
||||||
|
*
|
||||||
|
* # blowfish + bcrypt in the same class
|
||||||
|
*
|
||||||
|
* Altho there's a lot of Blowfish code that bcrypt doesn't re-use, bcrypt does re-use the
|
||||||
|
* initial S-boxes, the initial P-array and the int-only _encryptBlock() implementation.
|
||||||
|
*
|
||||||
|
* # Credit
|
||||||
|
*
|
||||||
|
* phpseclib's bcrypt implementation is based losely off of OpenSSH's implementation:
|
||||||
|
*
|
||||||
|
* https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bcrypt_pbkdf.c
|
||||||
|
*
|
||||||
* Here's a short example of how to use this library:
|
* Here's a short example of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
@ -74,6 +155,15 @@ class Blowfish extends Base
|
|||||||
*/
|
*/
|
||||||
var $cfb_init_len = 500;
|
var $cfb_init_len = 500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHA512 Object
|
||||||
|
*
|
||||||
|
* @see self::bcrypt_pbkdf
|
||||||
|
* @var object
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $sha512;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
|
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
|
||||||
*
|
*
|
||||||
@ -358,6 +448,7 @@ class Blowfish extends Base
|
|||||||
// unpack binary string in unsigned chars
|
// unpack binary string in unsigned chars
|
||||||
$key = array_values(unpack('C*', $this->key));
|
$key = array_values(unpack('C*', $this->key));
|
||||||
$keyl = count($key);
|
$keyl = count($key);
|
||||||
|
// with bcrypt $keyl will always be 16 (because the key is the sha512 of the key you provide)
|
||||||
for ($j = 0, $i = 0; $i < 18; ++$i) {
|
for ($j = 0, $i = 0; $i < 18; ++$i) {
|
||||||
// xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
|
// xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
|
||||||
for ($data = 0, $k = 0; $k < 4; ++$k) {
|
for ($data = 0, $k = 0; $k < 4; ++$k) {
|
||||||
@ -386,6 +477,233 @@ class Blowfish extends Base
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bcrypt
|
||||||
|
*
|
||||||
|
* @param string $sha2pass
|
||||||
|
* @param string $sha2salt
|
||||||
|
* @access private
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function _bcrypt_hash($sha2pass, $sha2salt)
|
||||||
|
{
|
||||||
|
$p = $this->parray;
|
||||||
|
$sbox0 = $this->sbox0;
|
||||||
|
$sbox1 = $this->sbox1;
|
||||||
|
$sbox2 = $this->sbox2;
|
||||||
|
$sbox3 = $this->sbox3;
|
||||||
|
|
||||||
|
$cdata = array_values(unpack('N*', 'OxychromaticBlowfishSwatDynamite'));
|
||||||
|
$sha2pass = array_values(unpack('N*', $sha2pass));
|
||||||
|
$sha2salt = array_values(unpack('N*', $sha2salt));
|
||||||
|
|
||||||
|
$this->_expandstate($sha2salt, $sha2pass, $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 0; $i < 64; $i++) {
|
||||||
|
$this->_expand0state($sha2salt, $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
$this->_expand0state($sha2pass, $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 0; $i < 64; $i++) {
|
||||||
|
for ($j = 0; $j < 8; $j+= 2) { // count($cdata) == 8
|
||||||
|
list($cdata[$j], $cdata[$j + 1]) = $this->_encryptBlockHelperFast($cdata[$j], $cdata[$j + 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = '';
|
||||||
|
for ($i = 0; $i < count($cdata); $i++) {
|
||||||
|
$output.= pack('L*', $cdata[$i]);
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs OpenSSH-style bcrypt
|
||||||
|
*
|
||||||
|
* @param string $pass
|
||||||
|
* @param string $salt
|
||||||
|
* @param int $keylen
|
||||||
|
* @param int $rounds
|
||||||
|
* @access public
|
||||||
|
* @return false|string
|
||||||
|
*/
|
||||||
|
function bcrypt_pbkdf($pass, $salt, $keylen, $rounds)
|
||||||
|
{
|
||||||
|
if (!CRYPT_BASE_USE_SAFE_INTVAL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!class_exists('Crypt_Hash')) {
|
||||||
|
include_once 'Crypt/Hash.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->sha512)) {
|
||||||
|
$this->sha512 = new Crypt_Hash('sha512');
|
||||||
|
}
|
||||||
|
|
||||||
|
$sha2pass = $this->sha512->hash($pass);
|
||||||
|
$results = array();
|
||||||
|
$count = 1;
|
||||||
|
while (32 * count($results) < $keylen) {
|
||||||
|
$countsalt = $salt . pack('N', $count++);
|
||||||
|
$sha2salt = $this->sha512->hash($countsalt);
|
||||||
|
$out = $tmpout = $this->_bcrypt_hash($sha2pass, $sha2salt);
|
||||||
|
for ($i = 1; $i < $rounds; $i++) {
|
||||||
|
$sha2salt = $this->sha512->hash($tmpout);
|
||||||
|
$tmpout = $this->_bcrypt_hash($sha2pass, $sha2salt);
|
||||||
|
$out^= $tmpout;
|
||||||
|
}
|
||||||
|
$results[] = $out;
|
||||||
|
}
|
||||||
|
$output = '';
|
||||||
|
for ($i = 0; $i < 32; $i++) {
|
||||||
|
foreach ($results as $result) {
|
||||||
|
$output.= $result[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return substr($output, 0, $keylen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key expansion without salt
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param int[] $key
|
||||||
|
* @param int[] $sbox0
|
||||||
|
* @param int[] $sbox1
|
||||||
|
* @param int[] $sbox2
|
||||||
|
* @param int[] $sbox3
|
||||||
|
* @param int[] $p
|
||||||
|
* @see self::_bcrypt_hash()
|
||||||
|
*/
|
||||||
|
function _expand0state($key, &$sbox0, &$sbox1, &$sbox2, &$sbox3, &$p)
|
||||||
|
{
|
||||||
|
// expand0state is basically the same thing as this:
|
||||||
|
//return $this->_expandstate(array_fill(0, 16, 0), $key);
|
||||||
|
// but this separate function eliminates a bunch of XORs and array lookups
|
||||||
|
|
||||||
|
$p = array(
|
||||||
|
$p[0] ^ $key[0],
|
||||||
|
$p[1] ^ $key[1],
|
||||||
|
$p[2] ^ $key[2],
|
||||||
|
$p[3] ^ $key[3],
|
||||||
|
$p[4] ^ $key[4],
|
||||||
|
$p[5] ^ $key[5],
|
||||||
|
$p[6] ^ $key[6],
|
||||||
|
$p[7] ^ $key[7],
|
||||||
|
$p[8] ^ $key[8],
|
||||||
|
$p[9] ^ $key[9],
|
||||||
|
$p[10] ^ $key[10],
|
||||||
|
$p[11] ^ $key[11],
|
||||||
|
$p[12] ^ $key[12],
|
||||||
|
$p[13] ^ $key[13],
|
||||||
|
$p[14] ^ $key[14],
|
||||||
|
$p[15] ^ $key[15],
|
||||||
|
$p[16] ^ $key[0],
|
||||||
|
$p[17] ^ $key[1]
|
||||||
|
);
|
||||||
|
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
list( $p[0], $p[1]) = $this->_encryptBlockHelperFast( 0, 0, $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[2], $p[3]) = $this->_encryptBlockHelperFast($p[ 0], $p[ 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[4], $p[5]) = $this->_encryptBlockHelperFast($p[ 2], $p[ 3], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[6], $p[7]) = $this->_encryptBlockHelperFast($p[ 4], $p[ 5], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[8], $p[9]) = $this->_encryptBlockHelperFast($p[ 6], $p[ 7], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[10], $p[11]) = $this->_encryptBlockHelperFast($p[ 8], $p[ 9], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[12], $p[13]) = $this->_encryptBlockHelperFast($p[10], $p[11], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[14], $p[15]) = $this->_encryptBlockHelperFast($p[12], $p[13], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[16], $p[17]) = $this->_encryptBlockHelperFast($p[14], $p[15], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
|
||||||
|
list($sbox0[0], $sbox0[1]) = $this->_encryptBlockHelperFast($p[16], $p[17], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2; $i < 256; $i+= 2) {
|
||||||
|
list($sbox0[$i], $sbox0[$i + 1]) = $this->_encryptBlockHelperFast($sbox0[$i - 2], $sbox0[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sbox1[0], $sbox1[1]) = $this->_encryptBlockHelperFast($sbox0[254], $sbox0[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2; $i < 256; $i+= 2) {
|
||||||
|
list($sbox1[$i], $sbox1[$i + 1]) = $this->_encryptBlockHelperFast($sbox1[$i - 2], $sbox1[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sbox2[0], $sbox2[1]) = $this->_encryptBlockHelperFast($sbox1[254], $sbox1[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2; $i < 256; $i+= 2) {
|
||||||
|
list($sbox2[$i], $sbox2[$i + 1]) = $this->_encryptBlockHelperFast($sbox2[$i - 2], $sbox2[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sbox3[0], $sbox3[1]) = $this->_encryptBlockHelperFast($sbox2[254], $sbox2[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2; $i < 256; $i+= 2) {
|
||||||
|
list($sbox3[$i], $sbox3[$i + 1]) = $this->_encryptBlockHelperFast($sbox3[$i - 2], $sbox3[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key expansion with salt
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param int[] $data
|
||||||
|
* @param int[] $key
|
||||||
|
* @param int[] $sbox0
|
||||||
|
* @param int[] $sbox1
|
||||||
|
* @param int[] $sbox2
|
||||||
|
* @param int[] $sbox3
|
||||||
|
* @param int[] $p
|
||||||
|
* @see self::_bcrypt_hash()
|
||||||
|
*/
|
||||||
|
function _expandstate($data, $key, &$sbox0, &$sbox1, &$sbox2, &$sbox3, &$p)
|
||||||
|
{
|
||||||
|
$p = array(
|
||||||
|
$p[0] ^ $key[0],
|
||||||
|
$p[1] ^ $key[1],
|
||||||
|
$p[2] ^ $key[2],
|
||||||
|
$p[3] ^ $key[3],
|
||||||
|
$p[4] ^ $key[4],
|
||||||
|
$p[5] ^ $key[5],
|
||||||
|
$p[6] ^ $key[6],
|
||||||
|
$p[7] ^ $key[7],
|
||||||
|
$p[8] ^ $key[8],
|
||||||
|
$p[9] ^ $key[9],
|
||||||
|
$p[10] ^ $key[10],
|
||||||
|
$p[11] ^ $key[11],
|
||||||
|
$p[12] ^ $key[12],
|
||||||
|
$p[13] ^ $key[13],
|
||||||
|
$p[14] ^ $key[14],
|
||||||
|
$p[15] ^ $key[15],
|
||||||
|
$p[16] ^ $key[0],
|
||||||
|
$p[17] ^ $key[1]
|
||||||
|
);
|
||||||
|
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
list( $p[0], $p[1]) = $this->_encryptBlockHelperFast($data[ 0] , $data[ 1] , $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[2], $p[3]) = $this->_encryptBlockHelperFast($data[ 2] ^ $p[ 0], $data[ 3] ^ $p[ 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[4], $p[5]) = $this->_encryptBlockHelperFast($data[ 4] ^ $p[ 2], $data[ 5] ^ $p[ 3], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[6], $p[7]) = $this->_encryptBlockHelperFast($data[ 6] ^ $p[ 4], $data[ 7] ^ $p[ 5], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list( $p[8], $p[9]) = $this->_encryptBlockHelperFast($data[ 8] ^ $p[ 6], $data[ 9] ^ $p[ 7], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[10], $p[11]) = $this->_encryptBlockHelperFast($data[10] ^ $p[ 8], $data[11] ^ $p[ 9], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[12], $p[13]) = $this->_encryptBlockHelperFast($data[12] ^ $p[10], $data[13] ^ $p[11], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[14], $p[15]) = $this->_encryptBlockHelperFast($data[14] ^ $p[12], $data[15] ^ $p[13], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
list($p[16], $p[17]) = $this->_encryptBlockHelperFast($data[ 0] ^ $p[14], $data[ 1] ^ $p[15], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
|
||||||
|
list($sbox0[0], $sbox0[1]) = $this->_encryptBlockHelperFast($data[2] ^ $p[16], $data[3] ^ $p[17], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2, $j = 4; $i < 256; $i+= 2, $j = ($j + 2) % 16) { // instead of 16 maybe count($data) would be better?
|
||||||
|
list($sbox0[$i], $sbox0[$i + 1]) = $this->_encryptBlockHelperFast($data[$j] ^ $sbox0[$i - 2], $data[$j + 1] ^ $sbox0[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sbox1[0], $sbox1[1]) = $this->_encryptBlockHelperFast($data[2] ^ $sbox0[254], $data[3] ^ $sbox0[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2, $j = 4; $i < 256; $i+= 2, $j = ($j + 2) % 16) {
|
||||||
|
list($sbox1[$i], $sbox1[$i + 1]) = $this->_encryptBlockHelperFast($data[$j] ^ $sbox1[$i - 2], $data[$j + 1] ^ $sbox1[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sbox2[0], $sbox2[1]) = $this->_encryptBlockHelperFast($data[2] ^ $sbox1[254], $data[3] ^ $sbox1[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2, $j = 4; $i < 256; $i+= 2, $j = ($j + 2) % 16) {
|
||||||
|
list($sbox2[$i], $sbox2[$i + 1]) = $this->_encryptBlockHelperFast($data[$j] ^ $sbox2[$i - 2], $data[$j + 1] ^ $sbox2[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sbox3[0], $sbox3[1]) = $this->_encryptBlockHelperFast($data[2] ^ $sbox2[254], $data[3] ^ $sbox2[255], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
for ($i = 2, $j = 4; $i < 256; $i+= 2, $j = ($j + 2) % 16) {
|
||||||
|
list($sbox3[$i], $sbox3[$i + 1]) = $this->_encryptBlockHelperFast($data[$j] ^ $sbox3[$i - 2], $data[$j + 1] ^ $sbox3[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts a block
|
* Encrypts a block
|
||||||
*
|
*
|
||||||
@ -406,18 +724,83 @@ class Blowfish extends Base
|
|||||||
$l = $in[1];
|
$l = $in[1];
|
||||||
$r = $in[2];
|
$r = $in[2];
|
||||||
|
|
||||||
for ($i = 0; $i < 16; $i+= 2) {
|
list($r, $l) = CRYPT_BASE_USE_SAFE_INTVAL ?
|
||||||
$l^= $p[$i];
|
$this->_encryptBlockHelperFast($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p) :
|
||||||
$r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
|
$this->_encryptBlockHelperSlow($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p);
|
||||||
$sb_2[$l >> 8 & 0xff]) +
|
|
||||||
$sb_3[$l & 0xff]);
|
|
||||||
|
|
||||||
$r^= $p[$i + 1];
|
return pack("N*", $r, $l);
|
||||||
$l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
|
}
|
||||||
$sb_2[$r >> 8 & 0xff]) +
|
|
||||||
$sb_3[$r & 0xff]);
|
/**
|
||||||
}
|
* Fast helper function for block encryption
|
||||||
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
|
*
|
||||||
|
* @access private
|
||||||
|
* @param int $x0
|
||||||
|
* @param int $x1
|
||||||
|
* @param int[] $sbox0
|
||||||
|
* @param int[] $sbox1
|
||||||
|
* @param int[] $sbox2
|
||||||
|
* @param int[] $sbox3
|
||||||
|
* @param int[] $p
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
function _encryptBlockHelperFast($x0, $x1, $sbox0, $sbox1, $sbox2, $sbox3, $p)
|
||||||
|
{
|
||||||
|
$x0 ^= $p[0];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14];
|
||||||
|
$x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15];
|
||||||
|
$x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16];
|
||||||
|
|
||||||
|
return array($x1 & 0xFFFFFFFF ^ $p[17], $x0 & 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slow helper function for block encryption
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param int $x0
|
||||||
|
* @param int $x1
|
||||||
|
* @param int[] $sbox0
|
||||||
|
* @param int[] $sbox1
|
||||||
|
* @param int[] $sbox2
|
||||||
|
* @param int[] $sbox3
|
||||||
|
* @param int[] $p
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
function _encryptBlockHelperSlow($x0, $x1, $sbox0, $sbox1, $sbox2, $sbox3, $p)
|
||||||
|
{
|
||||||
|
$x0^= $p[0];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14];
|
||||||
|
$x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15];
|
||||||
|
$x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16];
|
||||||
|
|
||||||
|
return array($x1 & 0xFFFFFFFF ^ $p[17], $x0 & 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1526,14 +1526,47 @@ class RSA
|
|||||||
if ($magic !== "openssh-key-v1\0") {
|
if ($magic !== "openssh-key-v1\0") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$options = $this->_string_shift($decoded, 24);
|
extract(unpack('Nlength', $this->_string_shift($decoded, 4)));
|
||||||
// \0\0\0\4none = ciphername
|
if (strlen($decoded) < $length) {
|
||||||
// \0\0\0\4none = kdfname
|
|
||||||
// \0\0\0\0 = kdfoptions
|
|
||||||
// \0\0\0\1 = numkeys
|
|
||||||
if ($options != "\0\0\0\4none\0\0\0\4none\0\0\0\0\0\0\0\1") {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$ciphername = $this->_string_shift($decoded, $length);
|
||||||
|
extract(unpack('Nlength', $this->_string_shift($decoded, 4)));
|
||||||
|
if (strlen($decoded) < $length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$kdfname = $this->_string_shift($decoded, $length);
|
||||||
|
extract(unpack('Nlength', $this->_string_shift($decoded, 4)));
|
||||||
|
if (strlen($decoded) < $length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$kdfoptions = $this->_string_shift($decoded, $length);
|
||||||
|
extract(unpack('Nnumkeys', $this->_string_shift($decoded, 4)));
|
||||||
|
if ($numkeys != 1 || ($ciphername != 'none' && $kdfname != 'bcrypt')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch ($ciphername) {
|
||||||
|
case 'none':
|
||||||
|
break;
|
||||||
|
case 'aes256-ctr':
|
||||||
|
extract(unpack('Nlength', $this->_string_shift($kdfoptions, 4)));
|
||||||
|
if (strlen($kdfoptions) < $length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$salt = $this->_string_shift($kdfoptions, $length);
|
||||||
|
extract(unpack('Nrounds', $this->_string_shift($kdfoptions, 4)));
|
||||||
|
if (!class_exists('Crypt_AES')) {
|
||||||
|
include_once 'Crypt/AES.php';
|
||||||
|
}
|
||||||
|
$crypto = new Crypt_AES(CRYPT_MODE_CTR);
|
||||||
|
$crypto->disablePadding();
|
||||||
|
if (!$crypto->setPassword($this->password, 'bcrypt', $salt, $rounds, 32)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
extract(unpack('Nlength', $this->_string_shift($decoded, 4)));
|
extract(unpack('Nlength', $this->_string_shift($decoded, 4)));
|
||||||
if (strlen($decoded) < $length) {
|
if (strlen($decoded) < $length) {
|
||||||
return false;
|
return false;
|
||||||
@ -1543,12 +1576,16 @@ class RSA
|
|||||||
if (strlen($decoded) < $length) {
|
if (strlen($decoded) < $length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$paddedKey = $this->_string_shift($decoded, $length);
|
|
||||||
|
|
||||||
if ($this->_string_shift($publicKey, 11) !== "\0\0\0\7ssh-rsa") {
|
if ($this->_string_shift($publicKey, 11) !== "\0\0\0\7ssh-rsa") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$paddedKey = $this->_string_shift($decoded, $length);
|
||||||
|
if (isset($crypto)) {
|
||||||
|
$paddedKey = $crypto->decrypt($paddedKey);
|
||||||
|
}
|
||||||
|
|
||||||
$checkint1 = $this->_string_shift($paddedKey, 4);
|
$checkint1 = $this->_string_shift($paddedKey, 4);
|
||||||
$checkint2 = $this->_string_shift($paddedKey, 4);
|
$checkint2 = $this->_string_shift($paddedKey, 4);
|
||||||
if (strlen($checkint1) != 4 || $checkint1 !== $checkint2) {
|
if (strlen($checkint1) != 4 || $checkint1 !== $checkint2) {
|
||||||
|
@ -630,4 +630,54 @@ Private-MAC: d26baf87446604974287b682ed9e0c00ce54e460e1cb719953a81291147b3c59
|
|||||||
$this->assertIsString($rsa->getPublicKey());
|
$this->assertIsString($rsa->getPublicKey());
|
||||||
$this->assertIsString($rsa->getPrivateKey());
|
$this->assertIsString($rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testOpenSSHEncrypted()
|
||||||
|
{
|
||||||
|
$key = '-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
LrIZULwMa4nI4Y+RkFftEponSYw=
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
||||||
|
';
|
||||||
|
|
||||||
|
$rsa = new RSA();
|
||||||
|
$rsa->setPassword('test');
|
||||||
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
|
$this->assertIsString($rsa->getPublicKey());
|
||||||
|
$this->assertIsString($rsa->getPrivateKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user