Updated phpseclib from git + requested style changes

This commit is contained in:
Henrik Kjölhede 2013-02-10 12:35:49 +01:00
parent c6622301e5
commit 1df8a5a774
17 changed files with 1432 additions and 915 deletions

View File

@ -10,6 +10,7 @@ AES, SSH-1, SSH-2, SFTP, and X.509
* [Browse Git](https://github.com/phpseclib/phpseclib) * [Browse Git](https://github.com/phpseclib/phpseclib)
* [Documentation](http://phpseclib.sourceforge.net/) * [Documentation](http://phpseclib.sourceforge.net/)
* [Support](http://www.frostjedi.com/phpbb/viewforum.php?f=46) * [Support](http://www.frostjedi.com/phpbb/viewforum.php?f=46)
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/latest/)
<img src="http://phpseclib.sourceforge.net/pear-icon.png" alt="PEAR Channel" width="16" height="16"> <img src="http://phpseclib.sourceforge.net/pear-icon.png" alt="PEAR Channel" width="16" height="16">
PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm) PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm)

View File

@ -166,6 +166,58 @@ class Crypt_AES extends Crypt_Rijndael {
*/ */
var $ecb; var $ecb;
/**
* The SubByte S-Box
*
* @see Crypt_AES::_encryptBlock()
* @var Array
* @access intern
*/
var $sbox = array(
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
);
/**
* The inverse SubByte S-Box
*
* @see Crypt_AES::_decryptBlock()
* @var Array
* @access intern
*/
var $isbox = array(
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
);
/** /**
* Default Constructor. * Default Constructor.
* *
@ -214,8 +266,6 @@ class Crypt_AES extends Crypt_Rijndael {
$this->mode = MCRYPT_MODE_CBC; $this->mode = MCRYPT_MODE_CBC;
} }
$this->debuffer = $this->enbuffer = '';
break; break;
default: default:
switch ($mode) { switch ($mode) {
@ -244,6 +294,36 @@ class Crypt_AES extends Crypt_Rijndael {
} }
} }
/**
* Extended Crypt_Rijndael::_setup()
*
* Optimizing the key schedule arrays ($w, $dw) for _encryptBlock() and _decryptBlock() after Crypt_Rijndael::_setup()
*
* @see Crypt_Rijndael::_setup()
* @access private
*/
function _setup()
{
if (!$this->changed) {
return;
}
$this->w = $this->dw = array();
parent::_setup();
$this->dw = array_reverse($this->dw);
$w = array_pop($this->w);
$dw = array_pop($this->dw);
foreach ($this->w as $r => $wr) {
foreach ($wr as $c => $wc) {
$w[] = $wc;
$dw[] = $this->dw[$r][$c];
}
}
$this->w = $w;
$this->dw = $dw;
}
/** /**
* Dummy function * Dummy function
* *
@ -257,7 +337,6 @@ class Crypt_AES extends Crypt_Rijndael {
return; return;
} }
/** /**
* Sets the initialization vector. (optional) * Sets the initialization vector. (optional)
* *
@ -295,51 +374,58 @@ class Crypt_AES extends Crypt_Rijndael {
function encrypt($plaintext) function encrypt($plaintext)
{ {
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) { if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
$changed = $this->changed;
$this->_mcryptSetup(); $this->_mcryptSetup();
/*
if ($this->mode == CRYPT_AES_MODE_CTR) {
$iv = $this->encryptIV;
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($plaintext), $iv));
$ciphertext = $plaintext ^ $xor;
if ($this->continuousBuffer) {
$this->encryptIV = $iv;
}
return $ciphertext;
}
*/
// re: http://phpseclib.sourceforge.net/cfb-demo.phps // re: http://phpseclib.sourceforge.net/cfb-demo.phps
// using mcrypt's default handing of CFB the above would output two different things. using phpseclib's // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
// rewritten CFB implementation the above outputs the same thing twice. // rewritten CFB implementation the above outputs the same thing twice.
if ($this->mode == 'ncfb') { if ($this->mode == 'ncfb' && $this->continuousBuffer) {
if ($changed) { $iv = &$this->encryptIV;
$this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, ''); $pos = &$this->enbuffer['pos'];
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); $len = strlen($plaintext);
$ciphertext = '';
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = 16 - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
$this->enbuffer['enmcrypt_init'] = true;
}
if ($len >= 16) {
if ($this->enbuffer['enmcrypt_init'] === false || $len > 280) {
if ($this->enbuffer['enmcrypt_init'] === true) {
mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
$this->enbuffer['enmcrypt_init'] = false;
}
$ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 16));
$iv = substr($ciphertext, -16);
$len%= 16;
} else {
while ($len >= 16) {
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 16);
$ciphertext.= $iv;
$len-= 16;
$i+= 16;
}
}
} }
if (strlen($this->enbuffer)) { if ($len) {
$ciphertext = $plaintext ^ substr($this->encryptIV, strlen($this->enbuffer)); $iv = mcrypt_generic($this->ecb, $iv);
$this->enbuffer.= $ciphertext; $block = $iv ^ substr($plaintext, -$len);
if (strlen($this->enbuffer) == 16) { $iv = substr_replace($iv, $block, 0, $len);
$this->encryptIV = $this->enbuffer; $ciphertext.= $block;
$this->enbuffer = ''; $pos = $len;
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
}
$plaintext = substr($plaintext, strlen($ciphertext));
} else {
$ciphertext = '';
}
$last_pos = strlen($plaintext) & 0xFFFFFFF0;
$ciphertext.= $last_pos ? mcrypt_generic($this->enmcrypt, substr($plaintext, 0, $last_pos)) : '';
if (strlen($plaintext) & 0xF) {
if (strlen($ciphertext)) {
$this->encryptIV = substr($ciphertext, -16);
}
$this->encryptIV = mcrypt_generic($this->ecb, $this->encryptIV);
$this->enbuffer = substr($plaintext, $last_pos) ^ $this->encryptIV;
$ciphertext.= $this->enbuffer;
} }
return $ciphertext; return $ciphertext;
@ -373,49 +459,41 @@ class Crypt_AES extends Crypt_Rijndael {
function decrypt($ciphertext) function decrypt($ciphertext)
{ {
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) { if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
$changed = $this->changed;
$this->_mcryptSetup(); $this->_mcryptSetup();
/*
if ($this->mode == CRYPT_AES_MODE_CTR) {
$iv = $this->decryptIV;
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($ciphertext), $iv));
$plaintext = $ciphertext ^ $xor;
if ($this->continuousBuffer) {
$this->decryptIV = $iv;
}
return $plaintext;
}
*/
if ($this->mode == 'ncfb') {
if ($changed) {
$this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}
if (strlen($this->debuffer)) { if ($this->mode == 'ncfb' && $this->continuousBuffer) {
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($this->debuffer)); $iv = &$this->decryptIV;
$pos = &$this->debuffer['pos'];
$this->debuffer.= substr($ciphertext, 0, strlen($plaintext)); $len = strlen($ciphertext);
if (strlen($this->debuffer) == 16) { $plaintext = '';
$this->decryptIV = $this->debuffer; $i = 0;
$this->debuffer = ''; if ($pos) {
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); $orig_pos = $pos;
$max = 16 - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
} }
$ciphertext = substr($ciphertext, strlen($plaintext)); // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
} else { $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$plaintext = ''; $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
} }
if ($len >= 16) {
$last_pos = strlen($ciphertext) & 0xFFFFFFF0; $cb = substr($ciphertext, $i, $len - $len % 16);
$plaintext.= $last_pos ? mdecrypt_generic($this->demcrypt, substr($ciphertext, 0, $last_pos)) : ''; $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$iv = substr($cb, -16);
if (strlen($ciphertext) & 0xF) { $len%= 16;
if (strlen($plaintext)) { }
$this->decryptIV = substr($ciphertext, $last_pos - 16, 16); if ($len) {
} $iv = mcrypt_generic($this->ecb, $iv);
$this->decryptIV = mcrypt_generic($this->ecb, $this->decryptIV); $plaintext.= $iv ^ substr($ciphertext, -$len);
$this->debuffer = substr($ciphertext, $last_pos); $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
$plaintext.= $this->debuffer ^ $this->decryptIV; $pos = $len;
} }
return $plaintext; return $plaintext;
@ -486,11 +564,20 @@ class Crypt_AES extends Crypt_Rijndael {
$this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, ''); $this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
$this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, ''); $this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
if ($mode == 'ncfb') {
$this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
}
} // else should mcrypt_generic_deinit be called? } // else should mcrypt_generic_deinit be called?
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv); mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv); mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
if ($this->mode == 'ncfb') {
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}
$this->changed = false; $this->changed = false;
} }
@ -506,53 +593,154 @@ class Crypt_AES extends Crypt_Rijndael {
*/ */
function _encryptBlock($in) function _encryptBlock($in)
{ {
$state = unpack('N*word', $in); $state = unpack('N*', $in);
$Nr = $this->Nr; $sbox = $this->sbox;
$w = $this->w; $w = $this->w;
$t0 = $this->t0; $t0 = $this->t0;
$t1 = $this->t1; $t1 = $this->t1;
$t2 = $this->t2; $t2 = $this->t2;
$t3 = $this->t3; $t3 = $this->t3;
// addRoundKey and reindex $state // addRoundKey
$state = array( $s0 = $state[1] ^ $w[4];
$state['word1'] ^ $w[0][0], $s1 = $state[2] ^ $w[5];
$state['word2'] ^ $w[0][1], $s2 = $state[3] ^ $w[6];
$state['word3'] ^ $w[0][2], $s3 = $state[4] ^ $w[7];
$state['word4'] ^ $w[0][3]
);
// shiftRows + subWord + mixColumns + addRoundKey // shiftRows + subWord + mixColumns + addRoundKey
// we could loop unroll this and use if statements to do more rounds as necessary, but, in my tests, that yields $e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[8];
// only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it. $e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[9];
for ($round = 1; $round < $this->Nr; $round++) { $e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[10];
$state = array( $e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[11];
$t0[$state[0] & 0xFF000000] ^ $t1[$state[1] & 0x00FF0000] ^ $t2[$state[2] & 0x0000FF00] ^ $t3[$state[3] & 0x000000FF] ^ $w[$round][0],
$t0[$state[1] & 0xFF000000] ^ $t1[$state[2] & 0x00FF0000] ^ $t2[$state[3] & 0x0000FF00] ^ $t3[$state[0] & 0x000000FF] ^ $w[$round][1],
$t0[$state[2] & 0xFF000000] ^ $t1[$state[3] & 0x00FF0000] ^ $t2[$state[0] & 0x0000FF00] ^ $t3[$state[1] & 0x000000FF] ^ $w[$round][2],
$t0[$state[3] & 0xFF000000] ^ $t1[$state[0] & 0x00FF0000] ^ $t2[$state[1] & 0x0000FF00] ^ $t3[$state[2] & 0x000000FF] ^ $w[$round][3]
);
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[12];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[13];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[14];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[15];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[16];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[17];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[18];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[19];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[20];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[21];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[22];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[23];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[24];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[25];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[26];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[27];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[28];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[29];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[30];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[31];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[32];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[33];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[34];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[35];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[36];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[37];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[38];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[39];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[40];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[41];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[42];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[43];
switch ($this->Nr) {
case 10:
break;
case 14:
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[52];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[53];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[54];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[55];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[56];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[57];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[58];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[59];
break;
case 12:
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
break;
case 13:
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[52];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[53];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[54];
$e3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[55];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
break;
default: // 11
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$e3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
} }
// subWord // subWord
$state = array( $e0 = $sbox[$e0 & 0xff] | ($sbox[($e0 >> 8) & 0xff] << 8) | ($sbox[($e0 >> 16) & 0xff] << 16) | ($sbox[($e0 >> 24) & 0xff] << 24);
$this->_subWord($state[0]), $e1 = $sbox[$e1 & 0xff] | ($sbox[($e1 >> 8) & 0xff] << 8) | ($sbox[($e1 >> 16) & 0xff] << 16) | ($sbox[($e1 >> 24) & 0xff] << 24);
$this->_subWord($state[1]), $e2 = $sbox[$e2 & 0xff] | ($sbox[($e2 >> 8) & 0xff] << 8) | ($sbox[($e2 >> 16) & 0xff] << 16) | ($sbox[($e2 >> 24) & 0xff] << 24);
$this->_subWord($state[2]), $e3 = $sbox[$e3 & 0xff] | ($sbox[($e3 >> 8) & 0xff] << 8) | ($sbox[($e3 >> 16) & 0xff] << 16) | ($sbox[($e3 >> 24) & 0xff] << 24);
$this->_subWord($state[3])
);
// shiftRows + addRoundKey // shiftRows + addRoundKey
$state = array( return pack('N*',
($state[0] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[3] & 0x000000FF) ^ $this->w[$this->Nr][0], ($e0 & 0xFF000000) ^ ($e1 & 0x00FF0000) ^ ($e2 & 0x0000FF00) ^ ($e3 & 0x000000FF) ^ $w[0],
($state[1] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[0] & 0x000000FF) ^ $this->w[$this->Nr][1], ($e1 & 0xFF000000) ^ ($e2 & 0x00FF0000) ^ ($e3 & 0x0000FF00) ^ ($e0 & 0x000000FF) ^ $w[1],
($state[2] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[1] & 0x000000FF) ^ $this->w[$this->Nr][2], ($e2 & 0xFF000000) ^ ($e3 & 0x00FF0000) ^ ($e0 & 0x0000FF00) ^ ($e1 & 0x000000FF) ^ $w[2],
($state[3] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[2] & 0x000000FF) ^ $this->w[$this->Nr][3] ($e3 & 0xFF000000) ^ ($e0 & 0x00FF0000) ^ ($e1 & 0x0000FF00) ^ ($e2 & 0x000000FF) ^ $w[3]
); );
return pack('N*', $state[0], $state[1], $state[2], $state[3]);
} }
/** /**
@ -567,43 +755,190 @@ class Crypt_AES extends Crypt_Rijndael {
*/ */
function _decryptBlock($in) function _decryptBlock($in)
{ {
$state = unpack('N*word', $in); $state = unpack('N*', $in);
$Nr = $this->Nr; $sbox = $this->isbox;
$dw = $this->dw; $dw = $this->dw;
$dt0 = $this->dt0; $dt0 = $this->dt0;
$dt1 = $this->dt1; $dt1 = $this->dt1;
$dt2 = $this->dt2; $dt2 = $this->dt2;
$dt3 = $this->dt3; $dt3 = $this->dt3;
// addRoundKey and reindex $state // addRoundKey
$state = array( $s0 = $state[1] ^ $dw[4];
$state['word1'] ^ $dw[$this->Nr][0], $s1 = $state[2] ^ $dw[5];
$state['word2'] ^ $dw[$this->Nr][1], $s2 = $state[3] ^ $dw[6];
$state['word3'] ^ $dw[$this->Nr][2], $s3 = $state[4] ^ $dw[7];
$state['word4'] ^ $dw[$this->Nr][3]
);
// invShiftRows + invSubBytes + invMixColumns + addRoundKey // invShiftRows + invSubBytes + invMixColumns + addRoundKey
for ($round = $this->Nr - 1; $round > 0; $round--) { $e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[8];
$state = array( $e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[9];
$dt0[$state[0] & 0xFF000000] ^ $dt1[$state[3] & 0x00FF0000] ^ $dt2[$state[2] & 0x0000FF00] ^ $dt3[$state[1] & 0x000000FF] ^ $dw[$round][0], $e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[10];
$dt0[$state[1] & 0xFF000000] ^ $dt1[$state[0] & 0x00FF0000] ^ $dt2[$state[3] & 0x0000FF00] ^ $dt3[$state[2] & 0x000000FF] ^ $dw[$round][1], $e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[11];
$dt0[$state[2] & 0xFF000000] ^ $dt1[$state[1] & 0x00FF0000] ^ $dt2[$state[0] & 0x0000FF00] ^ $dt3[$state[3] & 0x000000FF] ^ $dw[$round][2],
$dt0[$state[3] & 0xFF000000] ^ $dt1[$state[2] & 0x00FF0000] ^ $dt2[$state[1] & 0x0000FF00] ^ $dt3[$state[0] & 0x000000FF] ^ $dw[$round][3] $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[12];
); $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[13];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[14];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[15];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[16];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[17];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[18];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[19];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[20];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[21];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[22];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[23];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[24];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[25];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[26];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[27];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[28];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[29];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[30];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[31];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[32];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[33];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[34];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[35];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[36];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[37];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[38];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[39];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[40];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[41];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[42];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[43];
switch ($this->Nr) {
case 10:
break;
case 14:
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[52];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[53];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[54];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[56];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[57];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[58];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[59];
break;
case 12:
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
break;
case 13:
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[52];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[53];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[54];
$e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
break;
default: // 11
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
} }
// invShiftRows + invSubWord + addRoundKey // invSubWord
$state = array( $e0 = $sbox[$e0 & 0xff] | ($sbox[($e0 >> 8) & 0xff] << 8) | ($sbox[($e0 >> 16) & 0xff] << 16) | ($sbox[($e0 >> 24) & 0xff] << 24);
$this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $dw[0][0], $e1 = $sbox[$e1 & 0xff] | ($sbox[($e1 >> 8) & 0xff] << 8) | ($sbox[($e1 >> 16) & 0xff] << 16) | ($sbox[($e1 >> 24) & 0xff] << 24);
$this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $dw[0][1], $e2 = $sbox[$e2 & 0xff] | ($sbox[($e2 >> 8) & 0xff] << 8) | ($sbox[($e2 >> 16) & 0xff] << 16) | ($sbox[($e2 >> 24) & 0xff] << 24);
$this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $dw[0][2], $e3 = $sbox[$e3 & 0xff] | ($sbox[($e3 >> 8) & 0xff] << 8) | ($sbox[($e3 >> 16) & 0xff] << 16) | ($sbox[($e3 >> 24) & 0xff] << 24);
$this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $dw[0][3]
);
return pack('N*', $state[0], $state[1], $state[2], $state[3]); // invShiftRows + addRoundKey
return pack('N*',
($e0 & 0xFF000000) ^ ($e3 & 0x00FF0000) ^ ($e2 & 0x0000FF00) ^ ($e1 & 0x000000FF) ^ $dw[0],
($e1 & 0xFF000000) ^ ($e0 & 0x00FF0000) ^ ($e3 & 0x0000FF00) ^ ($e2 & 0x000000FF) ^ $dw[1],
($e2 & 0xFF000000) ^ ($e1 & 0x00FF0000) ^ ($e0 & 0x0000FF00) ^ ($e3 & 0x000000FF) ^ $dw[2],
($e3 & 0xFF000000) ^ ($e2 & 0x00FF0000) ^ ($e1 & 0x0000FF00) ^ ($e0 & 0x000000FF) ^ $dw[3]
);
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* The default behavior.
*
* @see Crypt_Rijndael::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
parent::enableContinuousBuffer();
if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
$this->enbuffer['enmcrypt_init'] = true;
$this->debuffer['demcrypt_init'] = true;
}
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_Rijndael::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
parent::disableContinuousBuffer();
if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
}
} }
} }

View File

@ -257,19 +257,19 @@ class Crypt_DES {
* Encryption buffer for CTR, OFB and CFB modes * Encryption buffer for CTR, OFB and CFB modes
* *
* @see Crypt_DES::encrypt() * @see Crypt_DES::encrypt()
* @var String * @var Array
* @access private * @access private
*/ */
var $enbuffer = ''; var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
/** /**
* Decryption buffer for CTR, OFB and CFB modes * Decryption buffer for CTR, OFB and CFB modes
* *
* @see Crypt_DES::decrypt() * @see Crypt_DES::decrypt()
* @var String * @var Array
* @access private * @access private
*/ */
var $debuffer = ''; var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
/** /**
* mcrypt resource for CFB mode * mcrypt resource for CFB mode
@ -316,6 +316,7 @@ class Crypt_DES {
break; break;
case CRYPT_DES_MODE_CFB: case CRYPT_DES_MODE_CFB:
$this->mode = 'ncfb'; $this->mode = 'ncfb';
$this->ecb = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
break; break;
case CRYPT_DES_MODE_OFB: case CRYPT_DES_MODE_OFB:
$this->mode = MCRYPT_MODE_NOFB; $this->mode = MCRYPT_MODE_NOFB;
@ -325,6 +326,8 @@ class Crypt_DES {
$this->paddable = true; $this->paddable = true;
$this->mode = MCRYPT_MODE_CBC; $this->mode = MCRYPT_MODE_CBC;
} }
$this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
$this->demcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
break; break;
default: default:
@ -363,7 +366,8 @@ class Crypt_DES {
function setKey($key) function setKey($key)
{ {
$this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? str_pad(substr($key, 0, 8), 8, chr(0)) : $this->_prepareKey($key); $this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? str_pad(substr($key, 0, 8), 8, chr(0)) : $this->_prepareKey($key);
$this->changed = true; $this->enchanged = true;
$this->dechanged = true;
} }
/** /**
@ -387,7 +391,7 @@ class Crypt_DES {
if (!isset($hash)) { if (!isset($hash)) {
$hash = 'sha1'; $hash = 'sha1';
} }
// WPA and WPA use the SSID as the salt // WPA and WPA2 use the SSID as the salt
if (!isset($salt)) { if (!isset($salt)) {
$salt = 'phpseclib/salt'; $salt = 'phpseclib/salt';
} }
@ -431,7 +435,8 @@ class Crypt_DES {
function setIV($iv) function setIV($iv)
{ {
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0)); $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
$this->changed = true; $this->enchanged = true;
$this->dechanged = true;
} }
/** /**
@ -443,29 +448,24 @@ class Crypt_DES {
* @see Crypt_DES::decrypt() * @see Crypt_DES::decrypt()
* @see Crypt_DES::encrypt() * @see Crypt_DES::encrypt()
* @access public * @access public
* @param Integer $length
* @param String $iv * @param String $iv
*/ */
function _generate_xor($length, &$iv) function _generate_xor(&$iv)
{ {
$xor = ''; $xor = $iv;
$num_blocks = ($length + 7) >> 3; for ($j = 4; $j <= 8; $j+=4) {
for ($i = 0; $i < $num_blocks; $i++) { $temp = substr($iv, -$j, 4);
$xor.= $iv; switch ($temp) {
for ($j = 4; $j <= 8; $j+=4) { case "\xFF\xFF\xFF\xFF":
$temp = substr($iv, -$j, 4); $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
switch ($temp) { break;
case "\xFF\xFF\xFF\xFF": case "\x7F\xFF\xFF\xFF":
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4); $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
break; break 2;
case "\x7F\xFF\xFF\xFF": default:
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4); extract(unpack('Ncount', $temp));
break 2; $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
default: break 2;
extract(unpack('Ncount', $temp));
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
break 2;
}
} }
} }
@ -497,48 +497,63 @@ class Crypt_DES {
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) { if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->enchanged) { if ($this->enchanged) {
if (!isset($this->enmcrypt)) {
$this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
}
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV); mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
if ($this->mode != 'ncfb') { if ($this->mode == 'ncfb') {
$this->enchanged = false; mcrypt_generic_init($this->ecb, $this->keys, "\0\0\0\0\0\0\0\0");
} }
$this->enchanged = false;
} }
if ($this->mode != 'ncfb') { if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
} else { } else {
if ($this->enchanged) { $iv = &$this->encryptIV;
$this->ecb = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, ''); $pos = &$this->enbuffer['pos'];
mcrypt_generic_init($this->ecb, $this->keys, "\0\0\0\0\0\0\0\0"); $len = strlen($plaintext);
$this->enchanged = false; $ciphertext = '';
} $i = 0;
if ($pos) {
if (strlen($this->enbuffer)) { $orig_pos = $pos;
$ciphertext = $plaintext ^ substr($this->encryptIV, strlen($this->enbuffer)); $max = 8 - $pos;
$this->enbuffer.= $ciphertext; if ($len >= $max) {
if (strlen($this->enbuffer) == 8) { $i = $max;
$this->encryptIV = $this->enbuffer; $len-= $max;
$this->enbuffer = ''; $pos = 0;
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV); } else {
$i = $len;
$pos+= $len;
$len = 0;
} }
$plaintext = substr($plaintext, strlen($ciphertext)); $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
} else { $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
$ciphertext = ''; $this->enbuffer['enmcrypt_init'] = true;
} }
if ($len >= 8) {
$last_pos = strlen($plaintext) & 0xFFFFFFF8; if ($this->enbuffer['enmcrypt_init'] === false || $len > 600) {
$ciphertext.= $last_pos ? mcrypt_generic($this->enmcrypt, substr($plaintext, 0, $last_pos)) : ''; if ($this->enbuffer['enmcrypt_init'] === true) {
mcrypt_generic_init($this->enmcrypt, $this->keys, $iv);
if (strlen($plaintext) & 0x7) { $this->enbuffer['enmcrypt_init'] = false;
if (strlen($ciphertext)) { }
$this->encryptIV = substr($ciphertext, -8); $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 8));
$iv = substr($ciphertext, -8);
$len%= 8;
} else {
while ($len >= 8) {
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 8);
$ciphertext.= $iv;
$len-= 8;
$i+= 8;
}
} }
$this->encryptIV = mcrypt_generic($this->ecb, $this->encryptIV); }
$this->enbuffer = substr($plaintext, $last_pos) ^ $this->encryptIV; if ($len) {
$ciphertext.= $this->enbuffer; $iv = mcrypt_generic($this->ecb, $iv);
$block = $iv ^ substr($plaintext, -$len);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
$pos = $len;
} }
return $ciphertext;
} }
if (!$this->continuousBuffer) { if (!$this->continuousBuffer) {
@ -578,14 +593,14 @@ class Crypt_DES {
if (strlen($buffer['encrypted'])) { if (strlen($buffer['encrypted'])) {
for ($i = 0; $i < strlen($plaintext); $i+=8) { for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8); $block = substr($plaintext, $i, 8);
$buffer['encrypted'].= $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT); $buffer['encrypted'].= $this->_processBlock($this->_generate_xor($xor), CRYPT_DES_ENCRYPT);
$key = $this->_string_shift($buffer['encrypted'], 8); $key = $this->_string_shift($buffer['encrypted'], 8);
$ciphertext.= $block ^ $key; $ciphertext.= $block ^ $key;
} }
} else { } else {
for ($i = 0; $i < strlen($plaintext); $i+=8) { for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8); $block = substr($plaintext, $i, 8);
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT); $key = $this->_processBlock($this->_generate_xor($xor), CRYPT_DES_ENCRYPT);
$ciphertext.= $block ^ $key; $ciphertext.= $block ^ $key;
} }
} }
@ -597,42 +612,51 @@ class Crypt_DES {
} }
break; break;
case CRYPT_DES_MODE_CFB: case CRYPT_DES_MODE_CFB:
if (!empty($buffer['xor'])) {
$ciphertext = $plaintext ^ $buffer['xor'];
$iv = $buffer['encrypted'] . $ciphertext;
$start = strlen($ciphertext);
$buffer['encrypted'].= $ciphertext;
$buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
} else {
$ciphertext = '';
$iv = $this->encryptIV;
$start = 0;
}
for ($i = $start; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8);
$xor = $this->_processBlock($iv, CRYPT_DES_ENCRYPT);
$iv = $block ^ $xor;
if ($continuousBuffer && strlen($iv) != 8) {
$buffer = array(
'encrypted' => $iv,
'xor' => substr($xor, strlen($iv))
);
}
$ciphertext.= $iv;
}
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->encryptIV = $iv; $iv = &$this->encryptIV;
$pos = &$buffer['pos'];
} else {
$iv = $this->encryptIV;
$pos = 0;
} }
break; $len = strlen($plaintext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = 8 - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
}
while ($len >= 8) {
$iv = $this->_processBlock($iv, CRYPT_DES_ENCRYPT) ^ substr($plaintext, $i, 8);
$ciphertext.= $iv;
$len-= 8;
$i+= 8;
}
if ($len) {
$iv = $this->_processBlock($iv, CRYPT_DES_ENCRYPT);
$block = $iv ^ substr($plaintext, $i);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
$pos = $len;
}
return $ciphertext;
case CRYPT_DES_MODE_OFB: case CRYPT_DES_MODE_OFB:
$xor = $this->encryptIV; $xor = $this->encryptIV;
if (strlen($buffer)) { if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($plaintext); $i+=8) { for ($i = 0; $i < strlen($plaintext); $i+=8) {
$xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT);
$buffer.= $xor; $buffer['xor'].= $xor;
$key = $this->_string_shift($buffer, 8); $key = $this->_string_shift($buffer['xor'], 8);
$ciphertext.= substr($plaintext, $i, 8) ^ $key; $ciphertext.= substr($plaintext, $i, 8) ^ $key;
} }
} else { } else {
@ -645,7 +669,7 @@ class Crypt_DES {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->encryptIV = $xor; $this->encryptIV = $xor;
if ($start = strlen($plaintext) & 7) { if ($start = strlen($plaintext) & 7) {
$buffer = substr($key, $start) . $buffer; $buffer['xor'] = substr($key, $start) . $buffer['xor'];
} }
} }
} }
@ -672,50 +696,48 @@ class Crypt_DES {
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) { if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->dechanged) { if ($this->dechanged) {
if (!isset($this->demcrypt)) {
$this->demcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
}
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV); mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
if ($this->mode != 'ncfb') { if ($this->mode == 'ncfb') {
$this->dechanged = false; mcrypt_generic_init($this->ecb, $this->keys, "\0\0\0\0\0\0\0\0");
} }
$this->dechanged = false;
} }
if ($this->mode != 'ncfb') { if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
} else { } else {
if ($this->dechanged) { $iv = &$this->decryptIV;
$this->ecb = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, ''); $pos = &$this->debuffer['pos'];
mcrypt_generic_init($this->ecb, $this->keys, "\0\0\0\0\0\0\0\0"); $len = strlen($ciphertext);
$this->dechanged = false; $plaintext = '';
} $i = 0;
if ($pos) {
if (strlen($this->debuffer)) { $orig_pos = $pos;
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($this->debuffer)); $max = 8 - $pos;
if ($len >= $max) {
$this->debuffer.= substr($ciphertext, 0, strlen($plaintext)); $i = $max;
if (strlen($this->debuffer) == 8) { $len-= $max;
$this->decryptIV = $this->debuffer; $pos = 0;
$this->debuffer = ''; } else {
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV); $i = $len;
$pos+= $len;
$len = 0;
} }
$ciphertext = substr($ciphertext, strlen($plaintext)); $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
} else { $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
$plaintext = '';
} }
if ($len >= 8) {
$last_pos = strlen($ciphertext) & 0xFFFFFFF8; $cb = substr($ciphertext, $i, $len - $len % 8);
$plaintext.= $last_pos ? mdecrypt_generic($this->demcrypt, substr($ciphertext, 0, $last_pos)) : ''; $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$iv = substr($cb, -8);
if (strlen($ciphertext) & 0x7) { $len%= 8;
if (strlen($plaintext)) { }
$this->decryptIV = substr($ciphertext, $last_pos - 8, 8); if ($len) {
} $iv = mcrypt_generic($this->ecb, $iv);
$this->decryptIV = mcrypt_generic($this->ecb, $this->decryptIV); $plaintext.= $iv ^ substr($ciphertext, -$len);
$this->debuffer = substr($ciphertext, $last_pos); $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
$plaintext.= $this->debuffer ^ $this->decryptIV; $pos = $len;
} }
return $plaintext; return $plaintext;
} }
@ -755,14 +777,14 @@ class Crypt_DES {
if (strlen($buffer['ciphertext'])) { if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=8) { for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8); $block = substr($ciphertext, $i, 8);
$buffer['ciphertext'].= $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT); $buffer['ciphertext'].= $this->_processBlock($this->_generate_xor($xor), CRYPT_DES_ENCRYPT);
$key = $this->_string_shift($buffer['ciphertext'], 8); $key = $this->_string_shift($buffer['ciphertext'], 8);
$plaintext.= $block ^ $key; $plaintext.= $block ^ $key;
} }
} else { } else {
for ($i = 0; $i < strlen($ciphertext); $i+=8) { for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8); $block = substr($ciphertext, $i, 8);
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT); $key = $this->_processBlock($this->_generate_xor($xor), CRYPT_DES_ENCRYPT);
$plaintext.= $block ^ $key; $plaintext.= $block ^ $key;
} }
} }
@ -774,42 +796,52 @@ class Crypt_DES {
} }
break; break;
case CRYPT_DES_MODE_CFB: case CRYPT_DES_MODE_CFB:
if (!empty($buffer['ciphertext'])) {
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext']));
$buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext));
if (strlen($buffer['ciphertext']) == 8) {
$xor = $this->_processBlock($buffer['ciphertext'], CRYPT_DES_ENCRYPT);
$buffer['ciphertext'] = '';
}
$start = strlen($plaintext);
$block = $this->decryptIV;
} else {
$plaintext = '';
$xor = $this->_processBlock($this->decryptIV, CRYPT_DES_ENCRYPT);
$start = 0;
}
for ($i = $start; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8);
$plaintext.= $block ^ $xor;
if ($continuousBuffer && strlen($block) != 8) {
$buffer['ciphertext'].= $block;
$block = $xor;
} else if (strlen($block) == 8) {
$xor = $this->_processBlock($block, CRYPT_DES_ENCRYPT);
}
}
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->decryptIV = $block; $iv = &$this->decryptIV;
$pos = &$buffer['pos'];
} else {
$iv = $this->decryptIV;
$pos = 0;
} }
break; $len = strlen($ciphertext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = 8 - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
}
while ($len >= 8) {
$iv = $this->_processBlock($iv, CRYPT_DES_ENCRYPT);
$cb = substr($ciphertext, $i, 8);
$plaintext.= $iv ^ $cb;
$iv = $cb;
$len-= 8;
$i+= 8;
}
if ($len) {
$iv = $this->_processBlock($iv, CRYPT_DES_ENCRYPT);
$plaintext.= $iv ^ substr($ciphertext, $i);
$iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
$pos = $len;
}
return $plaintext;
case CRYPT_DES_MODE_OFB: case CRYPT_DES_MODE_OFB:
$xor = $this->decryptIV; $xor = $this->decryptIV;
if (strlen($buffer)) { if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=8) { for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $this->_processBlock($xor, CRYPT_DES_ENCRYPT);
$buffer.= $xor; $buffer['xor'].= $xor;
$key = $this->_string_shift($buffer, 8); $key = $this->_string_shift($buffer['xor'], 8);
$plaintext.= substr($ciphertext, $i, 8) ^ $key; $plaintext.= substr($ciphertext, $i, 8) ^ $key;
} }
} else { } else {
@ -822,7 +854,7 @@ class Crypt_DES {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->decryptIV = $xor; $this->decryptIV = $xor;
if ($start = strlen($ciphertext) % 8) { if ($start = strlen($ciphertext) % 8) {
$buffer = substr($key, $start) . $buffer; $buffer['xor'] = substr($key, $start) . $buffer['xor'];
} }
} }
} }
@ -885,6 +917,13 @@ class Crypt_DES {
$this->continuousBuffer = false; $this->continuousBuffer = false;
$this->encryptIV = $this->iv; $this->encryptIV = $this->iv;
$this->decryptIV = $this->iv; $this->decryptIV = $this->iv;
$this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
$this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
if (CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT) {
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->iv);
mcrypt_generic_init($this->demcrypt, $this->keys, $this->iv);
}
} }
/** /**
@ -937,7 +976,7 @@ class Crypt_DES {
if (($length & 7) == 0) { if (($length & 7) == 0) {
return $text; return $text;
} else { } else {
$this->_handle_error("The plaintext's length ($length) is not a multiple of the block size (8)"); user_error("The plaintext's length ($length) is not a multiple of the block size (8)");
$this->padding = true; $this->padding = true;
} }
} }
@ -1289,25 +1328,7 @@ class Crypt_DES {
$string = substr($string, $index); $string = substr($string, $index);
return $substr; return $substr;
} }
/**
* Error Handler
*
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined.
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions.
*
* @param String $string
* @access private
*/
function _handle_error($err_msg) {
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception';
throw(new $class($err_msg));
} else {
user_error($err_msg);
}
}
} }
// vim: ts=4:sw=4:et: // vim: ts=4:sw=4:et:
// vim6: fdl=1: // vim6: fdl=1:

View File

@ -167,7 +167,6 @@ class Crypt_RC4 {
* *
* Determines whether or not the mcrypt extension should be used. * Determines whether or not the mcrypt extension should be used.
* *
* @param optional Integer $mode
* @return Crypt_RC4 * @return Crypt_RC4
* @access public * @access public
*/ */
@ -192,6 +191,9 @@ class Crypt_RC4 {
case defined('MCRYPT_RC4'); case defined('MCRYPT_RC4');
$this->mode = MCRYPT_RC4; $this->mode = MCRYPT_RC4;
} }
$this->encryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
$this->decryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
} }
} }
@ -209,6 +211,8 @@ class Crypt_RC4 {
$this->key = $key; $this->key = $key;
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) { if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
mcrypt_generic_init($this->encryptStream, $this->key, '');
mcrypt_generic_init($this->decryptStream, $this->key, '');
return; return;
} }
@ -250,7 +254,7 @@ class Crypt_RC4 {
if (!isset($hash)) { if (!isset($hash)) {
$hash = 'sha1'; $hash = 'sha1';
} }
// WPA and WPA use the SSID as the salt // WPA and WPA2 use the SSID as the salt
if (!isset($salt)) { if (!isset($salt)) {
$salt = 'phpseclib/salt'; $salt = 'phpseclib/salt';
} }
@ -349,18 +353,11 @@ class Crypt_RC4 {
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) { if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
$keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream'; $keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream';
if ($this->$keyStream === false) {
$this->$keyStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
mcrypt_generic_init($this->$keyStream, $this->key, '');
} else if (!$this->continuousBuffer) {
mcrypt_generic_init($this->$keyStream, $this->key, '');
}
$newText = mcrypt_generic($this->$keyStream, $text);
if (!$this->continuousBuffer) { if (!$this->continuousBuffer) {
mcrypt_generic_deinit($this->$keyStream); mcrypt_generic_init($this->$keyStream, $this->key, '');
} }
return $newText; return mcrypt_generic($this->$keyStream, $text);
} }
if ($this->encryptStream === false) { if ($this->encryptStream === false) {
@ -442,6 +439,11 @@ class Crypt_RC4 {
*/ */
function enableContinuousBuffer() function enableContinuousBuffer()
{ {
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
mcrypt_generic_init($this->encryptStream, $this->key, '');
mcrypt_generic_init($this->decryptStream, $this->key, '');
}
$this->continuousBuffer = true; $this->continuousBuffer = true;
} }
@ -457,7 +459,7 @@ class Crypt_RC4 {
{ {
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) { if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) {
$this->encryptIndex = $this->decryptIndex = array(0, 0); $this->encryptIndex = $this->decryptIndex = array(0, 0);
$this->setKey($this->key); $this->encryptStream = $this->decryptStream = false;
} }
$this->continuousBuffer = false; $this->continuousBuffer = false;
@ -508,24 +510,10 @@ class Crypt_RC4 {
*/ */
function _closeMCrypt() function _closeMCrypt()
{ {
if ( $this->encryptStream !== false ) { mcrypt_module_close($this->encryptStream);
if ( $this->continuousBuffer ) { mcrypt_module_close($this->decryptStream);
mcrypt_generic_deinit($this->encryptStream);
}
mcrypt_module_close($this->encryptStream);
$this->encryptStream = false;
}
if ( $this->decryptStream !== false ) {
if ( $this->continuousBuffer ) {
mcrypt_generic_deinit($this->decryptStream);
}
mcrypt_module_close($this->decryptStream);
$this->decryptStream = false;
}
} }
} }
// vim: ts=4:sw=4:et:
// vim6: fdl=1:

View File

@ -1746,7 +1746,7 @@ class Crypt_RSA {
{ {
$x = $x->toBytes(); $x = $x->toBytes();
if (strlen($x) > $xLen) { if (strlen($x) > $xLen) {
$this->_handle_error('Integer too large'); user_error('Integer too large');
return false; return false;
} }
return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
@ -1907,7 +1907,7 @@ class Crypt_RSA {
function _rsaep($m) function _rsaep($m)
{ {
if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
$this->_handle_error('Message representative out of range'); user_error('Message representative out of range');
return false; return false;
} }
return $this->_exponentiate($m); return $this->_exponentiate($m);
@ -1925,7 +1925,7 @@ class Crypt_RSA {
function _rsadp($c) function _rsadp($c)
{ {
if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) { if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) {
$this->_handle_error('Ciphertext representative out of range'); user_error('Ciphertext representative out of range');
return false; return false;
} }
return $this->_exponentiate($c); return $this->_exponentiate($c);
@ -1943,7 +1943,7 @@ class Crypt_RSA {
function _rsasp1($m) function _rsasp1($m)
{ {
if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
$this->_handle_error('Message representative out of range'); user_error('Message representative out of range');
return false; return false;
} }
return $this->_exponentiate($m); return $this->_exponentiate($m);
@ -1961,7 +1961,7 @@ class Crypt_RSA {
function _rsavp1($s) function _rsavp1($s)
{ {
if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) { if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) {
$this->_handle_error('Signature representative out of range'); user_error('Signature representative out of range');
return false; return false;
} }
return $this->_exponentiate($s); return $this->_exponentiate($s);
@ -2012,7 +2012,7 @@ class Crypt_RSA {
// be output. // be output.
if ($mLen > $this->k - 2 * $this->hLen - 2) { if ($mLen > $this->k - 2 * $this->hLen - 2) {
$this->_handle_error('Message too long'); user_error('Message too long');
return false; return false;
} }
@ -2073,7 +2073,7 @@ class Crypt_RSA {
// be output. // be output.
if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) { if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) {
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
@ -2082,7 +2082,7 @@ class Crypt_RSA {
$c = $this->_os2ip($c); $c = $this->_os2ip($c);
$m = $this->_rsadp($c); $m = $this->_rsadp($c);
if ($m === false) { if ($m === false) {
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
$em = $this->_i2osp($m, $this->k); $em = $this->_i2osp($m, $this->k);
@ -2100,12 +2100,12 @@ class Crypt_RSA {
$lHash2 = substr($db, 0, $this->hLen); $lHash2 = substr($db, 0, $this->hLen);
$m = substr($db, $this->hLen); $m = substr($db, $this->hLen);
if ($lHash != $lHash2) { if ($lHash != $lHash2) {
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
$m = ltrim($m, chr(0)); $m = ltrim($m, chr(0));
if (ord($m[0]) != 1) { if (ord($m[0]) != 1) {
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
@ -2130,7 +2130,7 @@ class Crypt_RSA {
// Length checking // Length checking
if ($mLen > $this->k - 11) { if ($mLen > $this->k - 11) {
$this->_handle_error('Message too long'); user_error('Message too long');
return false; return false;
} }
@ -2179,7 +2179,7 @@ class Crypt_RSA {
// Length checking // Length checking
if (strlen($c) != $this->k) { // or if k < 11 if (strlen($c) != $this->k) { // or if k < 11
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
@ -2189,7 +2189,7 @@ class Crypt_RSA {
$m = $this->_rsadp($c); $m = $this->_rsadp($c);
if ($m === false) { if ($m === false) {
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
$em = $this->_i2osp($m, $this->k); $em = $this->_i2osp($m, $this->k);
@ -2197,7 +2197,7 @@ class Crypt_RSA {
// EME-PKCS1-v1_5 decoding // EME-PKCS1-v1_5 decoding
if (ord($em[0]) != 0 || ord($em[1]) > 2) { if (ord($em[0]) != 0 || ord($em[1]) > 2) {
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
@ -2205,7 +2205,7 @@ class Crypt_RSA {
$m = substr($em, strlen($ps) + 3); $m = substr($em, strlen($ps) + 3);
if (strlen($ps) < 8) { if (strlen($ps) < 8) {
$this->_handle_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
@ -2233,7 +2233,7 @@ class Crypt_RSA {
$mHash = $this->hash->hash($m); $mHash = $this->hash->hash($m);
if ($emLen < $this->hLen + $sLen + 2) { if ($emLen < $this->hLen + $sLen + 2) {
$this->_handle_error('Encoding error'); user_error('Encoding error');
return false; return false;
} }
@ -2338,7 +2338,7 @@ class Crypt_RSA {
// Length checking // Length checking
if (strlen($s) != $this->k) { if (strlen($s) != $this->k) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return false; return false;
} }
@ -2349,12 +2349,12 @@ class Crypt_RSA {
$s2 = $this->_os2ip($s); $s2 = $this->_os2ip($s);
$m2 = $this->_rsavp1($s2); $m2 = $this->_rsavp1($s2);
if ($m2 === false) { if ($m2 === false) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return false; return false;
} }
$em = $this->_i2osp($m2, $modBits >> 3); $em = $this->_i2osp($m2, $modBits >> 3);
if ($em === false) { if ($em === false) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return false; return false;
} }
@ -2404,7 +2404,7 @@ class Crypt_RSA {
$tLen = strlen($t); $tLen = strlen($t);
if ($emLen < $tLen + 11) { if ($emLen < $tLen + 11) {
$this->_handle_error('Intended encoded message length too short'); user_error('Intended encoded message length too short');
return false; return false;
} }
@ -2430,7 +2430,7 @@ class Crypt_RSA {
$em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); $em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
if ($em === false) { if ($em === false) {
$this->_handle_error('RSA modulus too short'); user_error('RSA modulus too short');
return false; return false;
} }
@ -2459,7 +2459,7 @@ class Crypt_RSA {
// Length checking // Length checking
if (strlen($s) != $this->k) { if (strlen($s) != $this->k) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return false; return false;
} }
@ -2468,12 +2468,12 @@ class Crypt_RSA {
$s = $this->_os2ip($s); $s = $this->_os2ip($s);
$m2 = $this->_rsavp1($s); $m2 = $this->_rsavp1($s);
if ($m2 === false) { if ($m2 === false) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return false; return false;
} }
$em = $this->_i2osp($m2, $this->k); $em = $this->_i2osp($m2, $this->k);
if ($em === false) { if ($em === false) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return false; return false;
} }
@ -2481,7 +2481,7 @@ class Crypt_RSA {
$em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
if ($em2 === false) { if ($em2 === false) {
$this->_handle_error('RSA modulus too short'); user_error('RSA modulus too short');
return false; return false;
} }
@ -2643,22 +2643,4 @@ class Crypt_RSA {
return $this->_rsassa_pss_verify($message, $signature); return $this->_rsassa_pss_verify($message, $signature);
} }
} }
/**
* Error Handler
*
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined.
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions.
*
* @param String $string
* @access private
*/
function _handle_error($err_msg) {
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception';
throw(new $class($err_msg));
} else {
user_error($err_msg);
}
}
} }

View File

@ -90,7 +90,7 @@ function crypt_random_string($length) {
$fp = @fopen('/dev/urandom', 'rb'); $fp = @fopen('/dev/urandom', 'rb');
} }
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource() if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
return fread($urandom, $length); return fread($fp, $length);
} }
// method 3. pretty much does the same thing as method 2 per the following url: // method 3. pretty much does the same thing as method 2 per the following url:
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391 // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
@ -240,4 +240,4 @@ function crypt_random_string($length) {
$result.= $r; $result.= $r;
} }
return substr($result, 0, $length); return substr($result, 0, $length);
} }

View File

@ -387,7 +387,7 @@ class Crypt_Rijndael {
* @var String * @var String
* @access private * @access private
*/ */
var $enbuffer = array('encrypted' => '', 'xor' => ''); var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0);
/** /**
* Decryption buffer for CTR, OFB and CFB modes * Decryption buffer for CTR, OFB and CFB modes
@ -396,7 +396,7 @@ class Crypt_Rijndael {
* @var String * @var String
* @access private * @access private
*/ */
var $debuffer = array('ciphertext' => ''); var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0);
/** /**
* Default Constructor. * Default Constructor.
@ -510,13 +510,13 @@ class Crypt_Rijndael {
); );
for ($i = 0; $i < 256; $i++) { for ($i = 0; $i < 256; $i++) {
$t2[$i << 8] = (($t3[$i] << 8) & 0xFFFFFF00) | (($t3[$i] >> 24) & 0x000000FF); $t2[] = (($t3[$i] << 8) & 0xFFFFFF00) | (($t3[$i] >> 24) & 0x000000FF);
$t1[$i << 16] = (($t3[$i] << 16) & 0xFFFF0000) | (($t3[$i] >> 16) & 0x0000FFFF); $t1[] = (($t3[$i] << 16) & 0xFFFF0000) | (($t3[$i] >> 16) & 0x0000FFFF);
$t0[$i << 24] = (($t3[$i] << 24) & 0xFF000000) | (($t3[$i] >> 8) & 0x00FFFFFF); $t0[] = (($t3[$i] << 24) & 0xFF000000) | (($t3[$i] >> 8) & 0x00FFFFFF);
$dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($dt3[$i] >> 24) & 0x000000FF); $dt2[] = (($dt3[$i] << 8) & 0xFFFFFF00) | (($dt3[$i] >> 24) & 0x000000FF);
$dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($dt3[$i] >> 16) & 0x0000FFFF); $dt1[] = (($dt3[$i] << 16) & 0xFFFF0000) | (($dt3[$i] >> 16) & 0x0000FFFF);
$dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($dt3[$i] >> 8) & 0x00FFFFFF); $dt0[] = (($dt3[$i] << 24) & 0xFF000000) | (($dt3[$i] >> 8) & 0x00FFFFFF);
} }
} }
@ -599,7 +599,7 @@ class Crypt_Rijndael {
if (!isset($hash)) { if (!isset($hash)) {
$hash = 'sha1'; $hash = 'sha1';
} }
// WPA and WPA use the SSID as the salt // WPA and WPA2 use the SSID as the salt
if (!isset($salt)) { if (!isset($salt)) {
$salt = 'phpseclib'; $salt = 'phpseclib';
} }
@ -719,7 +719,6 @@ class Crypt_Rijndael {
$block_size = $this->block_size; $block_size = $this->block_size;
$buffer = &$this->enbuffer; $buffer = &$this->enbuffer;
$continuousBuffer = $this->continuousBuffer;
$ciphertext = ''; $ciphertext = '';
switch ($this->mode) { switch ($this->mode) {
case CRYPT_RIJNDAEL_MODE_ECB: case CRYPT_RIJNDAEL_MODE_ECB:
@ -741,7 +740,7 @@ class Crypt_Rijndael {
break; break;
case CRYPT_RIJNDAEL_MODE_CTR: case CRYPT_RIJNDAEL_MODE_CTR:
$xor = $this->encryptIV; $xor = $this->encryptIV;
if (!empty($buffer['encrypted'])) { if (strlen($buffer['encrypted'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size); $block = substr($plaintext, $i, $block_size);
$buffer['encrypted'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor)); $buffer['encrypted'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));
@ -763,42 +762,54 @@ class Crypt_Rijndael {
} }
break; break;
case CRYPT_RIJNDAEL_MODE_CFB: case CRYPT_RIJNDAEL_MODE_CFB:
if (!empty($buffer['xor'])) { // cfb loosely routines inspired by openssl's:
$ciphertext = $plaintext ^ $buffer['xor']; // http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1
$iv = $buffer['encrypted'] . $ciphertext;
$start = strlen($ciphertext);
$buffer['encrypted'].= $ciphertext;
$buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
} else {
$ciphertext = '';
$iv = $this->encryptIV;
$start = 0;
}
for ($i = $start; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
$xor = $this->_encryptBlock($iv);
$iv = $block ^ $xor;
if ($continuousBuffer && strlen($iv) != $block_size) {
$buffer = array(
'encrypted' => $iv,
'xor' => substr($xor, strlen($iv))
);
}
$ciphertext.= $iv;
}
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->encryptIV = $iv; $iv = &$this->encryptIV;
$pos = &$buffer['pos'];
} else {
$iv = $this->encryptIV;
$pos = 0;
}
$len = strlen($plaintext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
}
while ($len >= $block_size) {
$iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
$ciphertext.= $iv;
$len-= $block_size;
$i+= $block_size;
}
if ($len) {
$iv = $this->_encryptBlock($iv);
$block = $iv ^ substr($plaintext, $i);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
$pos = $len;
} }
break; break;
case CRYPT_RIJNDAEL_MODE_OFB: case CRYPT_RIJNDAEL_MODE_OFB:
$xor = $this->encryptIV; $xor = $this->encryptIV;
if (strlen($buffer)) { if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$xor = $this->_encryptBlock($xor); $xor = $this->_encryptBlock($xor);
$buffer.= $xor; $buffer['xor'].= $xor;
$key = $this->_string_shift($buffer, $block_size); $key = $this->_string_shift($buffer['xor'], $block_size);
$ciphertext.= substr($plaintext, $i, $block_size) ^ $key; $ciphertext.= substr($plaintext, $i, $block_size) ^ $key;
} }
} else { } else {
@ -811,7 +822,7 @@ class Crypt_Rijndael {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->encryptIV = $xor; $this->encryptIV = $xor;
if ($start = strlen($plaintext) % $block_size) { if ($start = strlen($plaintext) % $block_size) {
$buffer = substr($key, $start) . $buffer; $buffer['xor'] = substr($key, $start) . $buffer['xor'];
} }
} }
} }
@ -841,7 +852,6 @@ class Crypt_Rijndael {
$block_size = $this->block_size; $block_size = $this->block_size;
$buffer = &$this->debuffer; $buffer = &$this->debuffer;
$continuousBuffer = $this->continuousBuffer;
$plaintext = ''; $plaintext = '';
switch ($this->mode) { switch ($this->mode) {
case CRYPT_RIJNDAEL_MODE_ECB: case CRYPT_RIJNDAEL_MODE_ECB:
@ -862,7 +872,7 @@ class Crypt_Rijndael {
break; break;
case CRYPT_RIJNDAEL_MODE_CTR: case CRYPT_RIJNDAEL_MODE_CTR:
$xor = $this->decryptIV; $xor = $this->decryptIV;
if (!empty($buffer['ciphertext'])) { if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size); $block = substr($ciphertext, $i, $block_size);
$buffer['ciphertext'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor)); $buffer['ciphertext'].= $this->_encryptBlock($this->_generate_xor($block_size, $xor));
@ -879,47 +889,58 @@ class Crypt_Rijndael {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->decryptIV = $xor; $this->decryptIV = $xor;
if ($start = strlen($ciphertext) % $block_size) { if ($start = strlen($ciphertext) % $block_size) {
$buffer['ciphertext'] = substr($key, $start) . $buffer['encrypted']; $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
} }
} }
break; break;
case CRYPT_RIJNDAEL_MODE_CFB: case CRYPT_RIJNDAEL_MODE_CFB:
if (!empty($buffer['ciphertext'])) {
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext']));
$buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext));
if (strlen($buffer['ciphertext']) == $block_size) {
$xor = $this->_encryptBlock($buffer['ciphertext']);
$buffer['ciphertext'] = '';
}
$start = strlen($plaintext);
$block = $this->decryptIV;
} else {
$plaintext = '';
$xor = $this->_encryptBlock($this->decryptIV);
$start = 0;
}
for ($i = $start; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
$plaintext.= $block ^ $xor;
if ($continuousBuffer && strlen($block) != $block_size) {
$buffer['ciphertext'].= $block;
$block = $xor;
} else if (strlen($block) == $block_size) {
$xor = $this->_encryptBlock($block);
}
}
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->decryptIV = $block; $iv = &$this->decryptIV;
$pos = &$buffer['pos'];
} else {
$iv = $this->decryptIV;
$pos = 0;
}
$len = strlen($ciphertext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
}
while ($len >= $block_size) {
$iv = $this->_encryptBlock($iv);
$cb = substr($ciphertext, $i, $block_size);
$plaintext.= $iv ^ $cb;
$iv = $cb;
$len-= $block_size;
$i+= $block_size;
}
if ($len) {
$iv = $this->_encryptBlock($iv);
$plaintext.= $iv ^ substr($ciphertext, $i);
$iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
$pos = $len;
} }
break; break;
case CRYPT_RIJNDAEL_MODE_OFB: case CRYPT_RIJNDAEL_MODE_OFB:
$xor = $this->decryptIV; $xor = $this->decryptIV;
if (strlen($buffer)) { if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$xor = $this->_encryptBlock($xor); $xor = $this->_encryptBlock($xor);
$buffer.= $xor; $buffer['xor'].= $xor;
$key = $this->_string_shift($buffer, $block_size); $key = $this->_string_shift($buffer['xor'], $block_size);
$plaintext.= substr($ciphertext, $i, $block_size) ^ $key; $plaintext.= substr($ciphertext, $i, $block_size) ^ $key;
} }
} else { } else {
@ -932,7 +953,7 @@ class Crypt_Rijndael {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->decryptIV = $xor; $this->decryptIV = $xor;
if ($start = strlen($ciphertext) % $block_size) { if ($start = strlen($ciphertext) % $block_size) {
$buffer = substr($key, $start) . $buffer; $buffer['xor'] = substr($key, $start) . $buffer['xor'];
} }
} }
} }
@ -962,9 +983,9 @@ class Crypt_Rijndael {
$c = $this->c; $c = $this->c;
// addRoundKey // addRoundKey
$i = 0; $i = -1;
foreach ($words as $word) { foreach ($words as $word) {
$state[] = $word ^ $w[0][$i++]; $state[] = $word ^ $w[0][++$i];
} }
// fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components - // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
@ -976,31 +997,28 @@ class Crypt_Rijndael {
// [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
$temp = array(); $temp = array();
for ($round = 1; $round < $Nr; $round++) { for ($round = 1; $round < $Nr; ++$round) {
$i = 0; // $c[0] == 0 $i = 0; // $c[0] == 0
$j = $c[1]; $j = $c[1];
$k = $c[2]; $k = $c[2];
$l = $c[3]; $l = $c[3];
while ($i < $this->Nb) { while ($i < $Nb) {
$temp[$i] = $t0[$state[$i] & 0xFF000000] ^ $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
$t1[$state[$j] & 0x00FF0000] ^ $t1[$state[$j] >> 16 & 0x000000FF] ^
$t2[$state[$k] & 0x0000FF00] ^ $t2[$state[$k] >> 8 & 0x000000FF] ^
$t3[$state[$l] & 0x000000FF] ^ $t3[$state[$l] & 0x000000FF] ^
$w[$round][$i]; $w[$round][$i];
$i++; ++$i;
$j = ($j + 1) % $Nb; $j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb; $k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb; $l = ($l + 1) % $Nb;
} }
$state = $temp;
for ($i = 0; $i < $Nb; $i++) {
$state[$i] = $temp[$i];
}
} }
// subWord // subWord
for ($i = 0; $i < $Nb; $i++) { for ($i = 0; $i < $Nb; ++$i) {
$state[$i] = $this->_subWord($state[$i]); $state[$i] = $this->_subWord($state[$i]);
} }
@ -1009,22 +1027,38 @@ class Crypt_Rijndael {
$j = $c[1]; $j = $c[1];
$k = $c[2]; $k = $c[2];
$l = $c[3]; $l = $c[3];
while ($i < $this->Nb) { while ($i < $Nb) {
$temp[$i] = ($state[$i] & 0xFF000000) ^ $temp[$i] = ($state[$i] & 0xFF000000) ^
($state[$j] & 0x00FF0000) ^ ($state[$j] & 0x00FF0000) ^
($state[$k] & 0x0000FF00) ^ ($state[$k] & 0x0000FF00) ^
($state[$l] & 0x000000FF) ^ ($state[$l] & 0x000000FF) ^
$w[$Nr][$i]; $w[$Nr][$i];
$i++; ++$i;
$j = ($j + 1) % $Nb; $j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb; $k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb; $l = ($l + 1) % $Nb;
} }
// 100% ugly switch/case code... but ~5% faster (meaning: ~half second faster de/encrypting 1MB text, tested with php5.4.9 on linux/32bit with an AMD Athlon II P360 CPU) then the commented smart code below. Don't know it's worth or not
switch ($Nb) {
case 8:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
case 7:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
case 6:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
case 5:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
default:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
}
/*
$state = $temp; $state = $temp;
array_unshift($state, 'N*'); array_unshift($state, 'N*');
return call_user_func_array('pack', $state); return call_user_func_array('pack', $state);
*/
} }
/** /**
@ -1039,7 +1073,6 @@ class Crypt_Rijndael {
$state = array(); $state = array();
$words = unpack('N*word', $in); $words = unpack('N*word', $in);
$num_states = count($state);
$dw = $this->dw; $dw = $this->dw;
$dt0 = $this->dt0; $dt0 = $this->dt0;
$dt1 = $this->dt1; $dt1 = $this->dt1;
@ -1050,33 +1083,30 @@ class Crypt_Rijndael {
$c = $this->c; $c = $this->c;
// addRoundKey // addRoundKey
$i = 0; $i = -1;
foreach ($words as $word) { foreach ($words as $word) {
$state[] = $word ^ $dw[$Nr][$i++]; $state[] = $word ^ $dw[$Nr][++$i];
} }
$temp = array(); $temp = array();
for ($round = $Nr - 1; $round > 0; $round--) { for ($round = $Nr - 1; $round > 0; --$round) {
$i = 0; // $c[0] == 0 $i = 0; // $c[0] == 0
$j = $Nb - $c[1]; $j = $Nb - $c[1];
$k = $Nb - $c[2]; $k = $Nb - $c[2];
$l = $Nb - $c[3]; $l = $Nb - $c[3];
while ($i < $Nb) { while ($i < $Nb) {
$temp[$i] = $dt0[$state[$i] & 0xFF000000] ^ $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
$dt1[$state[$j] & 0x00FF0000] ^ $dt1[$state[$j] >> 16 & 0x000000FF] ^
$dt2[$state[$k] & 0x0000FF00] ^ $dt2[$state[$k] >> 8 & 0x000000FF] ^
$dt3[$state[$l] & 0x000000FF] ^ $dt3[$state[$l] & 0x000000FF] ^
$dw[$round][$i]; $dw[$round][$i];
$i++; ++$i;
$j = ($j + 1) % $Nb; $j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb; $k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb; $l = ($l + 1) % $Nb;
} }
$state = $temp;
for ($i = 0; $i < $Nb; $i++) {
$state[$i] = $temp[$i];
}
} }
// invShiftRows + invSubWord + addRoundKey // invShiftRows + invSubWord + addRoundKey
@ -1091,17 +1121,31 @@ class Crypt_Rijndael {
($state[$j] & 0x00FF0000) | ($state[$j] & 0x00FF0000) |
($state[$k] & 0x0000FF00) | ($state[$k] & 0x0000FF00) |
($state[$l] & 0x000000FF)); ($state[$l] & 0x000000FF));
$i++; ++$i;
$j = ($j + 1) % $Nb; $j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb; $k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb; $l = ($l + 1) % $Nb;
} }
switch ($Nb) {
case 8:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
case 7:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
case 6:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
case 5:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
default:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
}
/*
$state = $temp; $state = $temp;
array_unshift($state, 'N*'); array_unshift($state, 'N*');
return call_user_func_array('pack', $state); return call_user_func_array('pack', $state);
*/
} }
/** /**
@ -1201,10 +1245,10 @@ class Crypt_Rijndael {
$j = 0; $j = 0;
while ($j < $this->Nb) { while ($j < $this->Nb) {
$dw = $this->_subWord($this->w[$row][$j]); $dw = $this->_subWord($this->w[$row][$j]);
$temp[$j] = $this->dt0[$dw & 0xFF000000] ^ $temp[$j] = $this->dt0[$dw >> 24 & 0x000000FF] ^
$this->dt1[$dw & 0x00FF0000] ^ $this->dt1[$dw >> 16 & 0x000000FF] ^
$this->dt2[$dw & 0x0000FF00] ^ $this->dt2[$dw >> 8 & 0x000000FF] ^
$this->dt3[$dw & 0x000000FF]; $this->dt3[$dw & 0x000000FF];
$j++; $j++;
} }
$this->dw[$row] = $temp; $this->dw[$row] = $temp;
@ -1255,17 +1299,18 @@ class Crypt_Rijndael {
$sbox3 = array(); $sbox3 = array();
for ($i = 0; $i < 256; $i++) { for ($i = 0; $i < 256; $i++) {
$sbox1[$i << 8] = $sbox0[$i] << 8; $sbox1[] = $sbox0[$i] << 8;
$sbox2[$i << 16] = $sbox0[$i] << 16; $sbox2[] = $sbox0[$i] << 16;
$sbox3[$i << 24] = $sbox0[$i] << 24; $sbox3[] = $sbox0[$i] << 24;
} }
} }
return $sbox0[$word & 0x000000FF] | return $sbox0[$word & 0x000000FF] |
$sbox1[$word & 0x0000FF00] | $sbox1[$word >> 8 & 0x000000FF] |
$sbox2[$word & 0x00FF0000] | $sbox2[$word >> 16 & 0x000000FF] |
$sbox3[$word & 0xFF000000]; $sbox3[$word >> 24 & 0x000000FF];
} }
/** /**
* Performs inverse S-Box substitutions * Performs inverse S-Box substitutions
@ -1301,16 +1346,16 @@ class Crypt_Rijndael {
$sbox3 = array(); $sbox3 = array();
for ($i = 0; $i < 256; $i++) { for ($i = 0; $i < 256; $i++) {
$sbox1[$i << 8] = $sbox0[$i] << 8; $sbox1[] = $sbox0[$i] << 8;
$sbox2[$i << 16] = $sbox0[$i] << 16; $sbox2[] = $sbox0[$i] << 16;
$sbox3[$i << 24] = $sbox0[$i] << 24; $sbox3[] = $sbox0[$i] << 24;
} }
} }
return $sbox0[$word & 0x000000FF] | return $sbox0[$word & 0x000000FF] |
$sbox1[$word & 0x0000FF00] | $sbox1[$word >> 8 & 0x000000FF] |
$sbox2[$word & 0x00FF0000] | $sbox2[$word >> 16 & 0x000000FF] |
$sbox3[$word & 0xFF000000]; $sbox3[$word >> 24 & 0x000000FF];
} }
/** /**
@ -1365,7 +1410,7 @@ class Crypt_Rijndael {
if ($length % $this->block_size == 0) { if ($length % $this->block_size == 0) {
return $text; return $text;
} else { } else {
$this->_handle_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})"); user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
$this->padding = true; $this->padding = true;
} }
} }
@ -1454,6 +1499,8 @@ class Crypt_Rijndael {
$this->continuousBuffer = false; $this->continuousBuffer = false;
$this->encryptIV = $this->iv; $this->encryptIV = $this->iv;
$this->decryptIV = $this->iv; $this->decryptIV = $this->iv;
$this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0);
$this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0);
} }
/** /**
@ -1472,24 +1519,6 @@ class Crypt_Rijndael {
$string = substr($string, $index); $string = substr($string, $index);
return $substr; return $substr;
} }
/**
* Error Handler
*
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined.
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions.
*
* @param String $string
* @access private
*/
function _handle_error($err_msg) {
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception';
throw(new $class($err_msg));
} else {
user_error($err_msg);
}
}
} }
// vim: ts=4:sw=4:et: // vim: ts=4:sw=4:et:

View File

@ -212,19 +212,19 @@ class Crypt_TripleDES {
* Encryption buffer for CTR, OFB and CFB modes * Encryption buffer for CTR, OFB and CFB modes
* *
* @see Crypt_TripleDES::encrypt() * @see Crypt_TripleDES::encrypt()
* @var String * @var Array
* @access private * @access private
*/ */
var $enbuffer = ''; var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
/** /**
* Decryption buffer for CTR, OFB and CFB modes * Decryption buffer for CTR, OFB and CFB modes
* *
* @see Crypt_TripleDES::decrypt() * @see Crypt_TripleDES::decrypt()
* @var String * @var Array
* @access private * @access private
*/ */
var $debuffer = ''; var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
/** /**
* mcrypt resource for CFB mode * mcrypt resource for CFB mode
@ -287,6 +287,7 @@ class Crypt_TripleDES {
break; break;
case CRYPT_DES_MODE_CFB: case CRYPT_DES_MODE_CFB:
$this->mode = 'ncfb'; $this->mode = 'ncfb';
$this->ecb = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, '');
break; break;
case CRYPT_DES_MODE_OFB: case CRYPT_DES_MODE_OFB:
$this->mode = MCRYPT_MODE_NOFB; $this->mode = MCRYPT_MODE_NOFB;
@ -296,6 +297,8 @@ class Crypt_TripleDES {
$this->paddable = true; $this->paddable = true;
$this->mode = MCRYPT_MODE_CBC; $this->mode = MCRYPT_MODE_CBC;
} }
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
break; break;
default: default:
@ -384,7 +387,7 @@ class Crypt_TripleDES {
if (!isset($hash)) { if (!isset($hash)) {
$hash = 'sha1'; $hash = 'sha1';
} }
// WPA and WPA use the SSID as the salt // WPA and WPA2 use the SSID as the salt
if (!isset($salt)) { if (!isset($salt)) {
$salt = 'phpseclib'; $salt = 'phpseclib';
} }
@ -444,29 +447,24 @@ class Crypt_TripleDES {
* @see Crypt_TripleDES::decrypt() * @see Crypt_TripleDES::decrypt()
* @see Crypt_TripleDES::encrypt() * @see Crypt_TripleDES::encrypt()
* @access private * @access private
* @param Integer $length
* @param String $iv * @param String $iv
*/ */
function _generate_xor($length, &$iv) function _generate_xor(&$iv)
{ {
$xor = ''; $xor = $iv;
$num_blocks = ($length + 7) >> 3; for ($j = 4; $j <= 8; $j+=4) {
for ($i = 0; $i < $num_blocks; $i++) { $temp = substr($iv, -$j, 4);
$xor.= $iv; switch ($temp) {
for ($j = 4; $j <= 8; $j+=4) { case "\xFF\xFF\xFF\xFF":
$temp = substr($iv, -$j, 4); $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
switch ($temp) { break;
case "\xFF\xFF\xFF\xFF": case "\x7F\xFF\xFF\xFF":
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4); $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
break; break 2;
case "\x7F\xFF\xFF\xFF": default:
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4); extract(unpack('Ncount', $temp));
break 2; $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
default: break 2;
extract(unpack('Ncount', $temp));
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
break 2;
}
} }
} }
@ -494,48 +492,64 @@ class Crypt_TripleDES {
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) { if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->enchanged) { if ($this->enchanged) {
if (!isset($this->enmcrypt)) {
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
}
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
if ($this->mode != 'ncfb') { if ($this->mode == 'ncfb') {
$this->enchanged = false; mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
} }
$this->enchanged = false;
} }
if ($this->mode != 'ncfb') { if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
} else { } else {
if ($this->enchanged) { $iv = &$this->encryptIV;
$this->ecb = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, ''); $pos = &$this->enbuffer['pos'];
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0"); $len = strlen($plaintext);
$this->enchanged = false; $ciphertext = '';
} $i = 0;
if ($pos) {
if (strlen($this->enbuffer)) { $orig_pos = $pos;
$ciphertext = $plaintext ^ substr($this->encryptIV, strlen($this->enbuffer)); $max = 8 - $pos;
$this->enbuffer.= $ciphertext; if ($len >= $max) {
if (strlen($this->enbuffer) == 8) { $i = $max;
$this->encryptIV = $this->enbuffer; $len-= $max;
$this->enbuffer = ''; $pos = 0;
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); } else {
$i = $len;
$pos+= $len;
$len = 0;
} }
$plaintext = substr($plaintext, strlen($ciphertext)); $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
} else { $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
$ciphertext = ''; $this->enbuffer['enmcrypt_init'] = true;
} }
if ($len >= 8) {
$last_pos = strlen($plaintext) & 0xFFFFFFF8; if ($this->enbuffer['enmcrypt_init'] === false || $len > 950) {
$ciphertext.= $last_pos ? mcrypt_generic($this->enmcrypt, substr($plaintext, 0, $last_pos)) : ''; if ($this->enbuffer['enmcrypt_init'] === true) {
mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
if (strlen($plaintext) & 0x7) { $this->enbuffer['enmcrypt_init'] = false;
if (strlen($ciphertext)) { }
$this->encryptIV = substr($ciphertext, -8); $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 8));
$iv = substr($ciphertext, -8);
$i = strlen($ciphertext);
$len%= 8;
} else {
while ($len >= 8) {
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 8);
$ciphertext.= $iv;
$len-= 8;
$i+= 8;
}
} }
$this->encryptIV = mcrypt_generic($this->ecb, $this->encryptIV); }
$this->enbuffer = substr($plaintext, $last_pos) ^ $this->encryptIV; if ($len) {
$ciphertext.= $this->enbuffer; $iv = mcrypt_generic($this->ecb, $iv);
$block = $iv ^ substr($plaintext, $i);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
$pos = $len;
} }
return $ciphertext;
} }
if (!$this->continuousBuffer) { if (!$this->continuousBuffer) {
@ -591,7 +605,7 @@ class Crypt_TripleDES {
if (strlen($buffer['encrypted'])) { if (strlen($buffer['encrypted'])) {
for ($i = 0; $i < strlen($plaintext); $i+=8) { for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8); $block = substr($plaintext, $i, 8);
$key = $this->_generate_xor(8, $xor); $key = $this->_generate_xor($xor);
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT); $key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
@ -602,7 +616,7 @@ class Crypt_TripleDES {
} else { } else {
for ($i = 0; $i < strlen($plaintext); $i+=8) { for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8); $block = substr($plaintext, $i, 8);
$key = $this->_generate_xor(8, $xor); $key = $this->_generate_xor($xor);
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT); $key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
@ -612,12 +626,12 @@ class Crypt_TripleDES {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->encryptIV = $xor; $this->encryptIV = $xor;
if ($start = strlen($plaintext) & 7) { if ($start = strlen($plaintext) & 7) {
$buffer['encrypted'] = substr($key, $start) . $buffer; $buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
} }
} }
break; break;
case CRYPT_DES_MODE_CFB: case CRYPT_DES_MODE_CFB:
if (!empty($buffer['xor'])) { if (strlen($buffer['xor'])) {
$ciphertext = $plaintext ^ $buffer['xor']; $ciphertext = $plaintext ^ $buffer['xor'];
$iv = $buffer['encrypted'] . $ciphertext; $iv = $buffer['encrypted'] . $ciphertext;
$start = strlen($ciphertext); $start = strlen($ciphertext);
@ -651,13 +665,13 @@ class Crypt_TripleDES {
break; break;
case CRYPT_DES_MODE_OFB: case CRYPT_DES_MODE_OFB:
$xor = $this->encryptIV; $xor = $this->encryptIV;
if (strlen($buffer)) { if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($plaintext); $i+=8) { for ($i = 0; $i < strlen($plaintext); $i+=8) {
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT); $xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
$buffer.= $xor; $buffer['xor'].= $xor;
$key = $this->_string_shift($buffer, 8); $key = $this->_string_shift($buffer['xor'], 8);
$ciphertext.= substr($plaintext, $i, 8) ^ $key; $ciphertext.= substr($plaintext, $i, 8) ^ $key;
} }
} else { } else {
@ -672,7 +686,7 @@ class Crypt_TripleDES {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->encryptIV = $xor; $this->encryptIV = $xor;
if ($start = strlen($plaintext) & 7) { if ($start = strlen($plaintext) & 7) {
$buffer = substr($key, $start) . $buffer; $buffer['xor'] = substr($key, $start) . $buffer['xor'];
} }
} }
} }
@ -702,50 +716,49 @@ class Crypt_TripleDES {
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) { if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->dechanged) { if ($this->dechanged) {
if (!isset($this->demcrypt)) {
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
}
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
if ($this->mode != 'ncfb') { if ($this->mode == 'ncfb') {
$this->dechanged = false; mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
} }
$this->dechanged = false;
} }
if ($this->mode != 'ncfb') { if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
} else { } else {
if ($this->dechanged) { $iv = &$this->decryptIV;
$this->ecb = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, ''); $pos = &$this->debuffer['pos'];
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0"); $len = strlen($ciphertext);
$this->dechanged = false; $plaintext = '';
} $i = 0;
if ($pos) {
if (strlen($this->debuffer)) { $orig_pos = $pos;
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($this->debuffer)); $max = 8 - $pos;
if ($len >= $max) {
$this->debuffer.= substr($ciphertext, 0, strlen($plaintext)); $i = $max;
if (strlen($this->debuffer) == 8) { $len-= $max;
$this->decryptIV = $this->debuffer; $pos = 0;
$this->debuffer = ''; } else {
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); $i = $len;
$pos+= $len;
$len = 0;
} }
$ciphertext = substr($ciphertext, strlen($plaintext)); $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
} else { $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
$plaintext = '';
} }
if ($len >= 8) {
$last_pos = strlen($ciphertext) & 0xFFFFFFF8; $cb = substr($ciphertext, $i, $len - $len % 8);
$plaintext.= $last_pos ? mdecrypt_generic($this->demcrypt, substr($ciphertext, 0, $last_pos)) : ''; $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$iv = substr($cb, -8);
if (strlen($ciphertext) & 0x7) { $len%= 8;
if (strlen($plaintext)) { }
$this->decryptIV = substr($ciphertext, $last_pos - 8, 8); if ($len) {
} $iv = mcrypt_generic($this->ecb, $iv);
$this->decryptIV = mcrypt_generic($this->ecb, $this->decryptIV); $cb = substr($ciphertext, -$len);
$this->debuffer = substr($ciphertext, $last_pos); $plaintext.= $iv ^ $cb;
$plaintext.= $this->debuffer ^ $this->decryptIV; $iv = substr_replace($iv, $cb, 0, $len);
$pos = $len;
} }
return $plaintext; return $plaintext;
} }
@ -764,7 +777,7 @@ class Crypt_TripleDES {
$des = $this->des; $des = $this->des;
$buffer = &$this->enbuffer; $buffer = &$this->debuffer;
$continuousBuffer = $this->continuousBuffer; $continuousBuffer = $this->continuousBuffer;
$plaintext = ''; $plaintext = '';
switch ($this->mode) { switch ($this->mode) {
@ -796,7 +809,7 @@ class Crypt_TripleDES {
if (strlen($buffer['ciphertext'])) { if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=8) { for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8); $block = substr($ciphertext, $i, 8);
$key = $this->_generate_xor(8, $xor); $key = $this->_generate_xor($xor);
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT); $key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
@ -807,7 +820,7 @@ class Crypt_TripleDES {
} else { } else {
for ($i = 0; $i < strlen($ciphertext); $i+=8) { for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8); $block = substr($ciphertext, $i, 8);
$key = $this->_generate_xor(8, $xor); $key = $this->_generate_xor($xor);
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT); $key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
@ -822,17 +835,19 @@ class Crypt_TripleDES {
} }
break; break;
case CRYPT_DES_MODE_CFB: case CRYPT_DES_MODE_CFB:
if (!empty($buffer['ciphertext'])) { if (strlen($buffer['ciphertext'])) {
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext'])); $plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext']));
$buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext)); $buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext));
if (strlen($buffer['ciphertext']) == 8) { if (strlen($buffer['ciphertext']) != 8) {
$block = $this->decryptIV;
} else {
$block = $buffer['ciphertext'];
$xor = $des[0]->_processBlock($buffer['ciphertext'], CRYPT_DES_ENCRYPT); $xor = $des[0]->_processBlock($buffer['ciphertext'], CRYPT_DES_ENCRYPT);
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT); $xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
$buffer['ciphertext'] = ''; $buffer['ciphertext'] = '';
} }
$start = strlen($plaintext); $start = strlen($plaintext);
$block = $this->decryptIV;
} else { } else {
$plaintext = ''; $plaintext = '';
$xor = $des[0]->_processBlock($this->decryptIV, CRYPT_DES_ENCRYPT); $xor = $des[0]->_processBlock($this->decryptIV, CRYPT_DES_ENCRYPT);
@ -859,13 +874,13 @@ class Crypt_TripleDES {
break; break;
case CRYPT_DES_MODE_OFB: case CRYPT_DES_MODE_OFB:
$xor = $this->decryptIV; $xor = $this->decryptIV;
if (strlen($buffer)) { if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=8) { for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT); $xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
$buffer.= $xor; $buffer['xor'].= $xor;
$key = $this->_string_shift($buffer, 8); $key = $this->_string_shift($buffer['xor'], 8);
$plaintext.= substr($ciphertext, $i, 8) ^ $key; $plaintext.= substr($ciphertext, $i, 8) ^ $key;
} }
} else { } else {
@ -880,7 +895,7 @@ class Crypt_TripleDES {
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
$this->decryptIV = $xor; $this->decryptIV = $xor;
if ($start = strlen($ciphertext) & 7) { if ($start = strlen($ciphertext) & 7) {
$buffer = substr($key, $start) . $buffer; $buffer['xor'] = substr($key, $start) . $buffer['xor'];
} }
} }
} }
@ -948,6 +963,10 @@ class Crypt_TripleDES {
$this->continuousBuffer = false; $this->continuousBuffer = false;
$this->encryptIV = $this->iv; $this->encryptIV = $this->iv;
$this->decryptIV = $this->iv; $this->decryptIV = $this->iv;
$this->enchanged = true;
$this->dechanged = true;
$this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
$this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
if ($this->mode == CRYPT_DES_MODE_3CBC) { if ($this->mode == CRYPT_DES_MODE_3CBC) {
$this->des[0]->disableContinuousBuffer(); $this->des[0]->disableContinuousBuffer();

View File

@ -409,7 +409,7 @@ class File_ANSI {
case 47: $back = 'white'; break; case 47: $back = 'white'; break;
default: default:
$this->_handle_error('Unsupported attribute: ' . $mod); user_error('Unsupported attribute: ' . $mod);
$this->ansi = ''; $this->ansi = '';
break 2; break 2;
} }
@ -537,22 +537,4 @@ class File_ANSI {
return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $scrollback . '</pre>'; return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $scrollback . '</pre>';
} }
/**
* Error Handler
*
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined.
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions.
*
* @param String $string
* @access private
*/
function _handle_error($err_msg) {
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception';
throw(new $class($err_msg));
} else {
user_error($err_msg);
}
}
} }

View File

@ -959,7 +959,7 @@ class File_ASN1 {
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER: case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids); $oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
if ($oid === false) { if ($oid === false) {
$this->_handle_error('Invalid OID'); user_error('Invalid OID');
return false; return false;
} }
$value = ''; $value = '';
@ -1012,7 +1012,7 @@ class File_ASN1 {
$filters = $filters[$part]; $filters = $filters[$part];
} }
if ($filters === false) { if ($filters === false) {
$this->_handle_error('No filters defined for ' . implode('/', $loc)); user_error('No filters defined for ' . implode('/', $loc));
return false; return false;
} }
return $this->_encode_der($source, $filters + $mapping); return $this->_encode_der($source, $filters + $mapping);
@ -1036,7 +1036,7 @@ class File_ASN1 {
$value = $source ? "\xFF" : "\x00"; $value = $source ? "\xFF" : "\x00";
break; break;
default: default:
$this->_handle_error('Mapping provides no type definition for ' . implode('/', $this->location)); user_error('Mapping provides no type definition for ' . implode('/', $this->location));
return false; return false;
} }
@ -1274,22 +1274,4 @@ class File_ASN1 {
} }
return $out; return $out;
} }
/**
* Error Handler
*
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined.
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions.
*
* @param String $string
* @access private
*/
function _handle_error($err_msg) {
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception';
throw(new $class($err_msg));
} else {
user_error($err_msg);
}
}
} }

View File

@ -1647,7 +1647,7 @@ class File_X509 {
$map = $this->_getMapping($id); $map = $this->_getMapping($id);
if (is_bool($map)) { if (is_bool($map)) {
if (!$map) { if (!$map) {
$this->_handle_error($id . ' is not a currently supported extension'); user_error($id . ' is not a currently supported extension');
unset($extensions[$i]); unset($extensions[$i]);
} }
} else { } else {
@ -3156,8 +3156,8 @@ class File_X509 {
return false; return false;
} }
$startDate = !empty($this->startDate) ? $this->startDate : @date('M j H:i:s Y T'); $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M y H:i:s O');
$endDate = !empty($this->endDate) ? $this->endDate : @date('M j H:i:s Y T', strtotime('+1 year')); $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M y H:i:s O', strtotime('+1 year'));
$serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new Math_BigInteger(); $serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new Math_BigInteger();
$this->currentCert = array( $this->currentCert = array(
@ -3329,7 +3329,7 @@ class File_X509 {
$currentCert = isset($this->currentCert) ? $this->currentCert : NULL; $currentCert = isset($this->currentCert) ? $this->currentCert : NULL;
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : NULL; $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : NULL;
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('M j H:i:s Y T'); $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M y H:i:s O');
if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) { if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
$this->currentCert = $crl->currentCert; $this->currentCert = $crl->currentCert;
@ -3479,7 +3479,7 @@ class File_X509 {
*/ */
function setStartDate($date) function setStartDate($date)
{ {
$this->startDate = @date('M j H:i:s Y T', @strtotime($date)); $this->startDate = @date('D, d M y H:i:s O', @strtotime($date));
} }
/** /**
@ -3503,7 +3503,7 @@ class File_X509 {
$temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp; $temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
$this->endDate = new File_ASN1_Element($temp); $this->endDate = new File_ASN1_Element($temp);
} else { } else {
$this->endDate = @date('M j H:i:s Y T', @strtotime($date)); $this->endDate = @date('D, d M y H:i:s O', @strtotime($date));
} }
} }
@ -4131,7 +4131,7 @@ class File_X509 {
$i = count($rclist); $i = count($rclist);
$rclist[] = array('userCertificate' => $serial, $rclist[] = array('userCertificate' => $serial,
'revocationDate' => array('generalTime' => @date('M j H:i:s Y T'))); 'revocationDate' => array('generalTime' => @date('D, d M y H:i:s O')));
return $i; return $i;
} }
@ -4320,22 +4320,4 @@ class File_X509 {
return false; return false;
} }
/**
* Error Handler
*
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined.
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions.
*
* @param String $string
* @access private
*/
function _handle_error($err_msg) {
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception';
throw(new $class($err_msg));
} else {
user_error($err_msg);
}
}
} }

View File

@ -302,7 +302,7 @@ class Math_BigInteger {
} }
// '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48 // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
// '0' is the only value like this per http://php.net/empty // '0' is the only value like this per http://php.net/empty
if (empty($x) && (abs($base) != 256 || $x !== '0')) { if (empty($x) && (abs($base) != 256 || $x !== '0')) {
return; return;
} }

View File

@ -399,7 +399,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_VERSION) { if ($this->packet_type != NET_SFTP_VERSION) {
$this->_handle_error('Expected SSH_FXP_VERSION'); user_error('Expected SSH_FXP_VERSION');
return false; return false;
} }
@ -588,7 +588,7 @@ class Net_SFTP extends Net_SSH2 {
$this->_logError($response); $this->_logError($response);
return false; return false;
default: default:
$this->_handle_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
return false; return false;
} }
@ -645,7 +645,7 @@ class Net_SFTP extends Net_SSH2 {
$this->_logError($response); $this->_logError($response);
return false; return false;
default: default:
$this->_handle_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
return false; return false;
} }
@ -655,7 +655,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -736,7 +736,7 @@ class Net_SFTP extends Net_SSH2 {
$this->_logError($response); $this->_logError($response);
return false; return false;
default: default:
$this->_handle_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
return false; return false;
} }
@ -785,7 +785,7 @@ class Net_SFTP extends Net_SSH2 {
} }
break 2; break 2;
default: default:
$this->_handle_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
return false; return false;
} }
} }
@ -798,7 +798,7 @@ class Net_SFTP extends Net_SSH2 {
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3 // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1001,7 +1001,7 @@ class Net_SFTP extends Net_SSH2 {
return false; return false;
} }
$this->_handle_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
return false; return false;
} }
@ -1094,7 +1094,7 @@ class Net_SFTP extends Net_SSH2 {
*/ */
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1121,7 +1121,7 @@ class Net_SFTP extends Net_SSH2 {
return false; return false;
} }
$this->_handle_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
return false; return false;
} }
@ -1254,7 +1254,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1293,7 +1293,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1370,7 +1370,7 @@ class Net_SFTP extends Net_SSH2 {
$this->_logError($response); $this->_logError($response);
return false; return false;
default: default:
$this->_handle_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
return false; return false;
} }
@ -1379,7 +1379,7 @@ class Net_SFTP extends Net_SSH2 {
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3 // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
if ($mode & NET_SFTP_LOCAL_FILE) { if ($mode & NET_SFTP_LOCAL_FILE) {
if (!is_file($data)) { if (!is_file($data)) {
$this->_handle_error("$data is not a valid file"); user_error("$data is not a valid file");
return false; return false;
} }
$fp = @fopen($data, 'rb'); $fp = @fopen($data, 'rb');
@ -1430,7 +1430,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1458,7 +1458,7 @@ class Net_SFTP extends Net_SSH2 {
while ($i--) { while ($i--) {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1509,7 +1509,7 @@ class Net_SFTP extends Net_SSH2 {
$this->_logError($response); $this->_logError($response);
return false; return false;
default: default:
$this->_handle_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
return false; return false;
} }
@ -1548,7 +1548,7 @@ class Net_SFTP extends Net_SSH2 {
$this->_logError($response); $this->_logError($response);
break 2; break 2;
default: default:
$this->_handle_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS'); user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
if ($local_file !== false) { if ($local_file !== false) {
fclose($fp); fclose($fp);
} }
@ -1575,7 +1575,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1618,7 +1618,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }
@ -1737,7 +1737,7 @@ class Net_SFTP extends Net_SSH2 {
$response = $this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
$this->_handle_error('Expected SSH_FXP_STATUS'); user_error('Expected SSH_FXP_STATUS');
return false; return false;
} }

View File

@ -246,6 +246,14 @@ define('NET_SSH1_LOG_SIMPLE', 1);
* Returns the message content * Returns the message content
*/ */
define('NET_SSH1_LOG_COMPLEX', 2); define('NET_SSH1_LOG_COMPLEX', 2);
/**
* Outputs the content real-time
*/
define('NET_SSH2_LOG_REALTIME', 3);
/**
* Dumps the content real-time to a file
*/
define('NET_SSH2_LOG_REALTIME_FILE', 4);
/**#@-*/ /**#@-*/
/**#@+ /**#@+
@ -421,6 +429,33 @@ class Net_SSH1 {
*/ */
var $message_log = array(); var $message_log = array();
/**
* Real-time log file pointer
*
* @see Net_SSH1::_append_log()
* @var Resource
* @access private
*/
var $realtime_log_file;
/**
* Real-time log file size
*
* @see Net_SSH1::_append_log()
* @var Integer
* @access private
*/
var $realtime_log_size;
/**
* Real-time log file wrap boolean
*
* @see Net_SSH1::_append_log()
* @var Boolean
* @access private
*/
var $realtime_log_wrap;
/** /**
* Interactive Buffer * Interactive Buffer
* *
@ -430,6 +465,22 @@ class Net_SSH1 {
*/ */
var $interactiveBuffer = ''; var $interactiveBuffer = '';
/**
* Timeout
*
* @see Net_SSH1::setTimeout()
* @access private
*/
var $timeout;
/**
* Current Timeout
*
* @see Net_SSH2::_get_channel_packet()
* @access private
*/
var $curTimeout;
/** /**
* Default Constructor. * Default Constructor.
* *
@ -467,28 +518,23 @@ class Net_SSH1 {
$this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout); $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$this->fsock) { if (!$this->fsock) {
$this->_handle_error(rtrim("Cannot connect to $host. Error $errno. $errstr")); user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
return; return;
} }
$this->server_identification = $init_line = fgets($this->fsock, 255); $this->server_identification = $init_line = fgets($this->fsock, 255);
if (defined('NET_SSH1_LOGGING')) { if (defined('NET_SSH1_LOGGING')) {
$this->protocol_flags_log[] = '<-'; $this->_append_log('<-', $this->server_identification);
$this->protocol_flags_log[] = '->'; $this->_append_log('->', $this->identifier . "\r\n");
if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
$this->message_log[] = $this->server_identification;
$this->message_log[] = $this->identifier . "\r\n";
}
} }
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) { if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
$this->_handle_error('Can only connect to SSH servers'); user_error('Can only connect to SSH servers');
return; return;
} }
if ($parts[1][0] != 1) { if ($parts[1][0] != 1) {
$this->_handle_error("Cannot connect to SSH $parts[1] servers"); user_error("Cannot connect to SSH $parts[1] servers");
return; return;
} }
@ -496,7 +542,7 @@ class Net_SSH1 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) { if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
$this->_handle_error('Expected SSH_SMSG_PUBLIC_KEY'); user_error('Expected SSH_SMSG_PUBLIC_KEY');
return; return;
} }
@ -581,7 +627,7 @@ class Net_SSH1 {
$data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0); $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Error sending SSH_CMSG_SESSION_KEY'); user_error('Error sending SSH_CMSG_SESSION_KEY');
return; return;
} }
@ -611,7 +657,7 @@ class Net_SSH1 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) { if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
$this->_handle_error('Expected SSH_SMSG_SUCCESS'); user_error('Expected SSH_SMSG_SUCCESS');
return; return;
} }
@ -635,46 +681,65 @@ class Net_SSH1 {
$data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username); $data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Error sending SSH_CMSG_USER'); user_error('Error sending SSH_CMSG_USER');
return false; return false;
} }
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === true) {
return false;
}
if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= NET_SSH1_MASK_LOGIN; $this->bitmap |= NET_SSH1_MASK_LOGIN;
return true; return true;
} else if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) { } else if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
$this->_handle_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
return false; return false;
} }
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password); $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Error sending SSH_CMSG_AUTH_PASSWORD'); user_error('Error sending SSH_CMSG_AUTH_PASSWORD');
return false; return false;
} }
// remove the username and password from the last logged packet // remove the username and password from the last logged packet
if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) { if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen('password'), 'password'); $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen('password'), 'password');
$this->message_log[count($this->message_log) - 1] = $data; // zzzzz $this->message_log[count($this->message_log) - 1] = $data;
} }
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === true) {
return false;
}
if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= NET_SSH1_MASK_LOGIN; $this->bitmap |= NET_SSH1_MASK_LOGIN;
return true; return true;
} else if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) { } else if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
return false; return false;
} else { } else {
$this->_handle_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
return false; return false;
} }
} }
/**
* Set Timeout
*
* $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
* Setting $timeout to false or 0 will mean there is no timeout.
*
* @param Mixed $timeout
*/
function setTimeout($timeout)
{
$this->timeout = $this->curTimeout = $timeout;
}
/** /**
* Executes a command on a non-interactive shell, returns the output, and quits. * Executes a command on a non-interactive shell, returns the output, and quits.
* *
@ -698,14 +763,14 @@ class Net_SSH1 {
function exec($cmd, $block = true) function exec($cmd, $block = true)
{ {
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
$this->_handle_error('Operation disallowed prior to login()'); user_error('Operation disallowed prior to login()');
return false; return false;
} }
$data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd); $data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Error sending SSH_CMSG_EXEC_CMD'); user_error('Error sending SSH_CMSG_EXEC_CMD');
return false; return false;
} }
@ -716,10 +781,12 @@ class Net_SSH1 {
$output = ''; $output = '';
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
do { if ($response !== false) {
$output.= substr($response[NET_SSH1_RESPONSE_DATA], 4); do {
$response = $this->_get_binary_packet(); $output.= substr($response[NET_SSH1_RESPONSE_DATA], 4);
} while ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS); $response = $this->_get_binary_packet();
} while (is_array($response) && $response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS);
}
$data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION); $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
@ -750,21 +817,24 @@ class Net_SSH1 {
$data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, NET_SSH1_TTY_OP_END); $data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, NET_SSH1_TTY_OP_END);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Error sending SSH_CMSG_REQUEST_PTY'); user_error('Error sending SSH_CMSG_REQUEST_PTY');
return false; return false;
} }
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === true) {
return false;
}
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) { if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
$this->_handle_error('Expected SSH_SMSG_SUCCESS'); user_error('Expected SSH_SMSG_SUCCESS');
return false; return false;
} }
$data = pack('C', NET_SSH1_CMSG_EXEC_SHELL); $data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Error sending SSH_CMSG_EXEC_SHELL'); user_error('Error sending SSH_CMSG_EXEC_SHELL');
return false; return false;
} }
@ -803,12 +873,12 @@ class Net_SSH1 {
function read($expect, $mode = NET_SSH1_READ_SIMPLE) function read($expect, $mode = NET_SSH1_READ_SIMPLE)
{ {
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
$this->_handle_error('Operation disallowed prior to login()'); user_error('Operation disallowed prior to login()');
return false; return false;
} }
if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
$this->_handle_error('Unable to initiate an interactive shell session'); user_error('Unable to initiate an interactive shell session');
return false; return false;
} }
@ -816,13 +886,17 @@ class Net_SSH1 {
while (true) { while (true) {
if ($mode == NET_SSH1_READ_REGEX) { if ($mode == NET_SSH1_READ_REGEX) {
preg_match($expect, $this->interactiveBuffer, $matches); preg_match($expect, $this->interactiveBuffer, $matches);
$match = $matches[0]; $match = isset($matches[0]) ? $matches[0] : '';
} }
$pos = strpos($this->interactiveBuffer, $match); $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
if ($pos !== false) { if ($pos !== false) {
return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match)); return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match));
} }
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === true) {
return $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
}
$this->interactiveBuffer.= substr($response[NET_SSH1_RESPONSE_DATA], 4); $this->interactiveBuffer.= substr($response[NET_SSH1_RESPONSE_DATA], 4);
} }
} }
@ -838,19 +912,19 @@ class Net_SSH1 {
function interactiveWrite($cmd) function interactiveWrite($cmd)
{ {
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
$this->_handle_error('Operation disallowed prior to login()'); user_error('Operation disallowed prior to login()');
return false; return false;
} }
if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
$this->_handle_error('Unable to initiate an interactive shell session'); user_error('Unable to initiate an interactive shell session');
return false; return false;
} }
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd); $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Error sending SSH_CMSG_STDIN'); user_error('Error sending SSH_CMSG_STDIN');
return false; return false;
} }
@ -873,12 +947,12 @@ class Net_SSH1 {
function interactiveRead() function interactiveRead()
{ {
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
$this->_handle_error('Operation disallowed prior to login()'); user_error('Operation disallowed prior to login()');
return false; return false;
} }
if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
$this->_handle_error('Unable to initiate an interactive shell session'); user_error('Unable to initiate an interactive shell session');
return false; return false;
} }
@ -926,8 +1000,11 @@ class Net_SSH1 {
if ($this->bitmap) { if ($this->bitmap) {
$data = pack('C', NET_SSH1_CMSG_EOF); $data = pack('C', NET_SSH1_CMSG_EOF);
$this->_send_binary_packet($data); $this->_send_binary_packet($data);
/*
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === true) {
$response = array(NET_SSH1_RESPONSE_TYPE => -1);
}
switch ($response[NET_SSH1_RESPONSE_TYPE]) { switch ($response[NET_SSH1_RESPONSE_TYPE]) {
case NET_SSH1_SMSG_EXITSTATUS: case NET_SSH1_SMSG_EXITSTATUS:
$data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION); $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
@ -935,6 +1012,8 @@ class Net_SSH1 {
default: default:
$data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg); $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);
} }
*/
$data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);
$this->_send_binary_packet($data); $this->_send_binary_packet($data);
fclose($this->fsock); fclose($this->fsock);
@ -957,20 +1036,40 @@ class Net_SSH1 {
function _get_binary_packet() function _get_binary_packet()
{ {
if (feof($this->fsock)) { if (feof($this->fsock)) {
//$this->_handle_error('connection closed prematurely'); //user_error('connection closed prematurely');
return false; return false;
} }
if ($this->curTimeout) {
$read = array($this->fsock);
$write = $except = NULL;
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
//$this->_disconnect('Timeout');
return true;
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$this->curTimeout-= $elapsed;
}
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$temp = unpack('Nlength', fread($this->fsock, 4)); $temp = unpack('Nlength', fread($this->fsock, 4));
$padding_length = 8 - ($temp['length'] & 7); $padding_length = 8 - ($temp['length'] & 7);
$length = $temp['length'] + $padding_length; $length = $temp['length'] + $padding_length;
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 while ($length > 0) {
$raw = fread($this->fsock, $length); $temp = fread($this->fsock, $length);
$raw.= $temp;
$length-= strlen($temp);
}
$stop = strtok(microtime(), ' ') + strtok(''); $stop = strtok(microtime(), ' ') + strtok('');
if ($this->crypto !== false) { if (strlen($raw) && $this->crypto !== false) {
$raw = $this->crypto->decrypt($raw); $raw = $this->crypto->decrypt($raw);
} }
@ -981,7 +1080,7 @@ class Net_SSH1 {
$temp = unpack('Ncrc', substr($raw, -4)); $temp = unpack('Ncrc', substr($raw, -4));
//if ( $temp['crc'] != $this->_crc($padding . $type . $data) ) { //if ( $temp['crc'] != $this->_crc($padding . $type . $data) ) {
// $this->_handle_error('Bad CRC in packet from server'); // user_error('Bad CRC in packet from server');
// return false; // return false;
//} //}
@ -989,11 +1088,9 @@ class Net_SSH1 {
if (defined('NET_SSH1_LOGGING')) { if (defined('NET_SSH1_LOGGING')) {
$temp = isset($this->protocol_flags[$type]) ? $this->protocol_flags[$type] : 'UNKNOWN'; $temp = isset($this->protocol_flags[$type]) ? $this->protocol_flags[$type] : 'UNKNOWN';
$this->protocol_flags_log[] = '<- ' . $temp . $temp = '<- ' . $temp .
' (' . round($stop - $start, 4) . 's)'; ' (' . round($stop - $start, 4) . 's)';
if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) { $this->_append_log($temp, $data);
$this->message_log[] = $data;
}
} }
return array( return array(
@ -1012,25 +1109,18 @@ class Net_SSH1 {
* @return Boolean * @return Boolean
* @access private * @access private
*/ */
function _send_binary_packet($data) { function _send_binary_packet($data)
{
if (feof($this->fsock)) { if (feof($this->fsock)) {
//$this->_handle_error('connection closed prematurely'); //user_error('connection closed prematurely');
return false; return false;
} }
if (defined('NET_SSH1_LOGGING')) {
$temp = isset($this->protocol_flags[ord($data[0])]) ? $this->protocol_flags[ord($data[0])] : 'UNKNOWN';
$this->protocol_flags_log[] = '-> ' . $temp .
' (' . round($stop - $start, 4) . 's)';
if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
$this->message_log[] = substr($data, 1);
}
}
$length = strlen($data) + 4; $length = strlen($data) + 4;
$padding = crypt_random_string(8 - ($length & 7)); $padding = crypt_random_string(8 - ($length & 7));
$orig = $data;
$data = $padding . $data; $data = $padding . $data;
$data.= pack('N', $this->_crc($data)); $data.= pack('N', $this->_crc($data));
@ -1044,6 +1134,13 @@ class Net_SSH1 {
$result = strlen($packet) == fputs($this->fsock, $packet); $result = strlen($packet) == fputs($this->fsock, $packet);
$stop = strtok(microtime(), ' ') + strtok(''); $stop = strtok(microtime(), ' ') + strtok('');
if (defined('NET_SSH1_LOGGING')) {
$temp = isset($this->protocol_flags[ord($orig[0])]) ? $this->protocol_flags[ord($orig[0])] : 'UNKNOWN';
$temp = '-> ' . $temp .
' (' . round($stop - $start, 4) . 's)';
$this->_append_log($temp, $orig);
}
return $result; return $result;
} }
@ -1203,16 +1300,15 @@ class Net_SSH1 {
// Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation", // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation",
// under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL: // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL:
// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
$temp = chr(0) . chr(2);
$modulus = $key[1]->toBytes(); $modulus = $key[1]->toBytes();
$length = strlen($modulus) - strlen($m) - 3; $length = strlen($modulus) - strlen($m) - 3;
$temp = ''; $random = '';
while (strlen($temp) != $length) { while (strlen($random) != $length) {
$block = crypt_random_string($length - strlen($temp)); $block = crypt_random_string($length - strlen($random));
$block = str_replace("\x00", '', $block); $block = str_replace("\x00", '', $block);
$temp.= $block; $random.= $block;
} }
$temp.= chr(0) . $m; $temp = chr(0) . chr(2) . $random . chr(0) . $m;
$m = new Math_BigInteger($temp, 256); $m = new Math_BigInteger($temp, 256);
$m = $m->modPow($key[0], $key[1]); $m = $m->modPow($key[0], $key[1]);
@ -1288,7 +1384,7 @@ class Net_SSH1 {
$current_log = $message_log[$i]; $current_log = $message_log[$i];
$j = 0; $j = 0;
do { do {
if (!empty($current_log)) { if (strlen($current_log)) {
$output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 '; $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
} }
$fragment = $this->_string_shift($current_log, $short_width); $fragment = $this->_string_shift($current_log, $short_width);
@ -1305,7 +1401,7 @@ class Net_SSH1 {
$raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
$output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n"; $output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n";
$j++; $j++;
} while (!empty($current_log)); } while (strlen($current_log));
$output.= "\r\n"; $output.= "\r\n";
} }
@ -1416,20 +1512,66 @@ class Net_SSH1 {
} }
/** /**
* Error Handler * Logs data packets
* *
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined. * Makes sure that only the last 1MB worth of packets will be logged
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions.
* *
* @param String $string * @param String $data
* @access private * @access private
*/ */
function _handle_error($err_msg) { function _append_log($protocol_flags, $message)
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) { {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception'; switch (NET_SSH1_LOGGING) {
throw(new $class($err_msg)); // useful for benchmarks
} else { case NET_SSH1_LOG_SIMPLE:
user_error($err_msg); $this->protocol_flags_log[] = $protocol_flags;
} break;
// the most useful log for SSH1
case NET_SSH1_LOG_COMPLEX:
$this->protocol_flags_log[] = $protocol_flags;
$this->_string_shift($message);
$this->log_size+= strlen($message);
$this->message_log[] = $message;
while ($this->log_size > NET_SSH2_LOG_MAX_SIZE) {
$this->log_size-= strlen(array_shift($this->message_log));
array_shift($this->protocol_flags_log);
}
break;
// dump the output out realtime; packets may be interspersed with non packets,
// passwords won't be filtered out and select other packets may not be correctly
// identified
case NET_SSH1_LOG_REALTIME:
echo "<pre>\r\n" . $this->_format_log(array($message), array($protocol_flags)) . "\r\n</pre>\r\n";
@flush();
@ob_flush();
break;
// basically the same thing as NET_SSH1_LOG_REALTIME with the caveat that NET_SSH1_LOG_REALTIME_FILE
// needs to be defined and that the resultant log file will be capped out at NET_SSH1_LOG_MAX_SIZE.
// the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
// at the beginning of the file
case NET_SSH1_LOG_REALTIME_FILE:
if (!isset($this->realtime_log_file)) {
// PHP doesn't seem to like using constants in fopen()
$filename = NET_SSH2_LOG_REALTIME_FILE;
$fp = fopen($filename, 'w');
$this->realtime_log_file = $fp;
}
if (!is_resource($this->realtime_log_file)) {
break;
}
$entry = $this->_format_log(array($message), array($protocol_flags));
if ($this->realtime_log_wrap) {
$temp = "<<< START >>>\r\n";
$entry.= $temp;
fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
}
$this->realtime_log_size+= strlen($entry);
if ($this->realtime_log_size > NET_SSH1_LOG_MAX_SIZE) {
fseek($this->realtime_log_file, 0);
$this->realtime_log_size = strlen($entry);
$this->realtime_log_wrap = true;
}
fputs($this->realtime_log_file, $entry);
}
} }
} }

View File

@ -663,6 +663,7 @@ class Net_SSH2 {
* Real-time log file pointer * Real-time log file pointer
* *
* @see Net_SSH2::_append_log() * @see Net_SSH2::_append_log()
* @var Resource
* @access private * @access private
*/ */
var $realtime_log_file; var $realtime_log_file;
@ -671,6 +672,7 @@ class Net_SSH2 {
* Real-time log file size * Real-time log file size
* *
* @see Net_SSH2::_append_log() * @see Net_SSH2::_append_log()
* @var Integer
* @access private * @access private
*/ */
var $realtime_log_size; var $realtime_log_size;
@ -679,6 +681,7 @@ class Net_SSH2 {
* Has the signature been validated? * Has the signature been validated?
* *
* @see Net_SSH2::getServerPublicHostKey() * @see Net_SSH2::getServerPublicHostKey()
* @var Boolean
* @access private * @access private
*/ */
var $signature_validated = false; var $signature_validated = false;
@ -706,6 +709,14 @@ class Net_SSH2 {
*/ */
var $last_packet; var $last_packet;
/**
* Exit status returned from ssh if any
*
* @var Integer
* @access private
*/
var $exit_status;
/** /**
* Default Constructor. * Default Constructor.
* *
@ -793,7 +804,7 @@ class Net_SSH2 {
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout); $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$this->fsock) { if (!$this->fsock) {
$this->_handle_error(rtrim("Cannot connect to $host. Error $errno. $errstr")); user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
return; return;
} }
$elapsed = strtok(microtime(), ' ') + strtok('') - $start; $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
@ -801,7 +812,7 @@ class Net_SSH2 {
$timeout-= $elapsed; $timeout-= $elapsed;
if ($timeout <= 0) { if ($timeout <= 0) {
$this->_handle_error(rtrim("Cannot connect to $host. Timeout error")); user_error(rtrim("Cannot connect to $host. Timeout error"));
return; return;
} }
@ -814,7 +825,7 @@ class Net_SSH2 {
// on windows this returns a "Warning: Invalid CRT parameters detected" error // on windows this returns a "Warning: Invalid CRT parameters detected" error
// the !count() is done as a workaround for <https://bugs.php.net/42682> // the !count() is done as a workaround for <https://bugs.php.net/42682>
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->_handle_error(rtrim("Cannot connect to $host. Banner timeout")); user_error(rtrim("Cannot connect to $host. Banner timeout"));
return; return;
} }
@ -836,7 +847,7 @@ class Net_SSH2 {
} }
if (feof($this->fsock)) { if (feof($this->fsock)) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
@ -855,22 +866,17 @@ class Net_SSH2 {
} }
if (defined('NET_SSH2_LOGGING')) { if (defined('NET_SSH2_LOGGING')) {
$this->message_number_log[] = '<-'; $this->_append_log('<-', $extra . $temp);
$this->message_number_log[] = '->'; $this->_append_log('->', $this->identifier . "\r\n");
if (NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) {
$this->message_log[] = $extra . $temp;
$this->message_log[] = $this->identifier . "\r\n";
}
} }
$this->server_identifier = trim($temp, "\r\n"); $this->server_identifier = trim($temp, "\r\n");
if (!empty($extra)) { if (strlen($extra)) {
$this->errors[] = utf8_decode($extra); $this->errors[] = utf8_decode($extra);
} }
if ($matches[1] != '1.99' && $matches[1] != '2.0') { if ($matches[1] != '1.99' && $matches[1] != '2.0') {
$this->_handle_error("Cannot connect to SSH $matches[1] servers"); user_error("Cannot connect to SSH $matches[1] servers");
return; return;
} }
@ -878,12 +884,12 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return; return;
} }
if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) { if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
$this->_handle_error('Expected SSH_MSG_KEXINIT'); user_error('Expected SSH_MSG_KEXINIT');
return; return;
} }
@ -1025,7 +1031,7 @@ class Net_SSH2 {
// we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++); for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++);
if ($i == count($encryption_algorithms)) { if ($i == count($encryption_algorithms)) {
$this->_handle_error('No compatible server to client encryption algorithms found'); user_error('No compatible server to client encryption algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -1062,7 +1068,7 @@ class Net_SSH2 {
for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++); for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++);
if ($i == count($encryption_algorithms)) { if ($i == count($encryption_algorithms)) {
$this->_handle_error('No compatible client to server encryption algorithms found'); user_error('No compatible client to server encryption algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -1100,7 +1106,7 @@ class Net_SSH2 {
// through diffie-hellman key exchange a symmetric key is obtained // through diffie-hellman key exchange a symmetric key is obtained
for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++); for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++);
if ($i == count($kex_algorithms)) { if ($i == count($kex_algorithms)) {
$this->_handle_error('No compatible key exchange algorithms found'); user_error('No compatible key exchange algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -1152,19 +1158,19 @@ class Net_SSH2 {
$data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes); $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
if (!$this->_send_binary_packet($data)) { if (!$this->_send_binary_packet($data)) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
extract(unpack('Ctype', $this->_string_shift($response, 1))); extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_KEXDH_REPLY) { if ($type != NET_SSH2_MSG_KEXDH_REPLY) {
$this->_handle_error('Expected SSH_MSG_KEXDH_REPLY'); user_error('Expected SSH_MSG_KEXDH_REPLY');
return false; return false;
} }
@ -1202,12 +1208,12 @@ class Net_SSH2 {
for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++); for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++);
if ($i == count($server_host_key_algorithms)) { if ($i == count($server_host_key_algorithms)) {
$this->_handle_error('No compatible server host key algorithms found'); user_error('No compatible server host key algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) { if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) {
$this->_handle_error('Sever Host Key Algorithm Mismatch'); user_error('Sever Host Key Algorithm Mismatch');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -1222,14 +1228,14 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
extract(unpack('Ctype', $this->_string_shift($response, 1))); extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_NEWKEYS) { if ($type != NET_SSH2_MSG_NEWKEYS) {
$this->_handle_error('Expected SSH_MSG_NEWKEYS'); user_error('Expected SSH_MSG_NEWKEYS');
return false; return false;
} }
@ -1343,7 +1349,7 @@ class Net_SSH2 {
for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++); for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++);
if ($i == count($mac_algorithms)) { if ($i == count($mac_algorithms)) {
$this->_handle_error('No compatible client to server message authentication algorithms found'); user_error('No compatible client to server message authentication algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -1368,7 +1374,7 @@ class Net_SSH2 {
for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++); for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++);
if ($i == count($mac_algorithms)) { if ($i == count($mac_algorithms)) {
$this->_handle_error('No compatible server to client message authentication algorithms found'); user_error('No compatible server to client message authentication algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -1410,14 +1416,14 @@ class Net_SSH2 {
for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++); for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++);
if ($i == count($compression_algorithms)) { if ($i == count($compression_algorithms)) {
$this->_handle_error('No compatible server to client compression algorithms found'); user_error('No compatible server to client compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
$this->decompress = $compression_algorithms[$i] == 'zlib'; $this->decompress = $compression_algorithms[$i] == 'zlib';
for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++); for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++);
if ($i == count($compression_algorithms)) { if ($i == count($compression_algorithms)) {
$this->_handle_error('No compatible client to server compression algorithms found'); user_error('No compatible client to server compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
$this->compress = $compression_algorithms[$i] == 'zlib'; $this->compress = $compression_algorithms[$i] == 'zlib';
@ -1453,14 +1459,14 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
extract(unpack('Ctype', $this->_string_shift($response, 1))); extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) { if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
$this->_handle_error('Expected SSH_MSG_SERVICE_ACCEPT'); user_error('Expected SSH_MSG_SERVICE_ACCEPT');
return false; return false;
} }
@ -1481,7 +1487,7 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
@ -1517,7 +1523,7 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
@ -1589,7 +1595,7 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
@ -1702,7 +1708,7 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
@ -1737,7 +1743,7 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
@ -1890,7 +1896,7 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
@ -1901,7 +1907,7 @@ class Net_SSH2 {
break; break;
case NET_SSH2_MSG_CHANNEL_FAILURE: case NET_SSH2_MSG_CHANNEL_FAILURE:
default: default:
$this->_handle_error('Unable to request pseudo-terminal'); user_error('Unable to request pseudo-terminal');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
} }
@ -1942,12 +1948,12 @@ class Net_SSH2 {
$this->curTimeout = $this->timeout; $this->curTimeout = $this->timeout;
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
$this->_handle_error('Operation disallowed prior to login()'); user_error('Operation disallowed prior to login()');
return false; return false;
} }
if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) {
$this->_handle_error('Unable to initiate an interactive shell session'); user_error('Unable to initiate an interactive shell session');
return false; return false;
} }
@ -1955,9 +1961,9 @@ class Net_SSH2 {
while (true) { while (true) {
if ($mode == NET_SSH2_READ_REGEX) { if ($mode == NET_SSH2_READ_REGEX) {
preg_match($expect, $this->interactiveBuffer, $matches); preg_match($expect, $this->interactiveBuffer, $matches);
$match = isset($matches[0]) ? $matches[0] : array(); $match = isset($matches[0]) ? $matches[0] : '';
} }
$pos = !empty($match) ? strpos($this->interactiveBuffer, $match) : false; $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
if ($pos !== false) { if ($pos !== false) {
return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match)); return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match));
} }
@ -1981,12 +1987,12 @@ class Net_SSH2 {
function write($cmd) function write($cmd)
{ {
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
$this->_handle_error('Operation disallowed prior to login()'); user_error('Operation disallowed prior to login()');
return false; return false;
} }
if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) {
$this->_handle_error('Unable to initiate an interactive shell session'); user_error('Unable to initiate an interactive shell session');
return false; return false;
} }
@ -2031,16 +2037,15 @@ class Net_SSH2 {
function _get_binary_packet() function _get_binary_packet()
{ {
if (!is_resource($this->fsock) || feof($this->fsock)) { if (!is_resource($this->fsock) || feof($this->fsock)) {
$this->_handle_error('Connection closed prematurely'); user_error('Connection closed prematurely');
$this->bitmask = 0; $this->bitmask = 0;
return false; return false;
} }
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$raw = fread($this->fsock, $this->decrypt_block_size); $raw = fread($this->fsock, $this->decrypt_block_size);
$stop = strtok(microtime(), ' ') + strtok('');
if (empty($raw)) { if (!strlen($raw)) {
return ''; return '';
} }
@ -2048,22 +2053,31 @@ class Net_SSH2 {
$raw = $this->decrypt->decrypt($raw); $raw = $this->decrypt->decrypt($raw);
} }
if ($raw === false) { if ($raw === false) {
$this->_handle_error('Unable to decrypt content'); user_error('Unable to decrypt content');
return false; return false;
} }
extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5))); extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
$remaining_length = $packet_length + 4 - $this->decrypt_block_size; $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
// quoting <http://tools.ietf.org/html/rfc4253#section-6.1>,
// "implementations SHOULD check that the packet length is reasonable"
// PuTTY uses 0x9000 as the actual max packet size and so to shall we
if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
user_error('Invalid size');
return false;
}
$buffer = ''; $buffer = '';
while ($remaining_length > 0) { while ($remaining_length > 0) {
$temp = fread($this->fsock, $remaining_length); $temp = fread($this->fsock, $remaining_length);
$buffer.= $temp; $buffer.= $temp;
$remaining_length-= strlen($temp); $remaining_length-= strlen($temp);
} }
if (!empty($buffer)) { $stop = strtok(microtime(), ' ') + strtok('');
if (strlen($buffer)) {
$raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer; $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
$buffer = $temp = '';
} }
$payload = $this->_string_shift($raw, $packet_length - $padding_length - 1); $payload = $this->_string_shift($raw, $packet_length - $padding_length - 1);
@ -2072,7 +2086,7 @@ class Net_SSH2 {
if ($this->hmac_check !== false) { if ($this->hmac_check !== false) {
$hmac = fread($this->fsock, $this->hmac_size); $hmac = fread($this->fsock, $this->hmac_size);
if ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) { if ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
$this->_handle_error('Invalid HMAC'); user_error('Invalid HMAC');
return false; return false;
} }
} }
@ -2239,11 +2253,11 @@ class Net_SSH2 {
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
if ($response === false) { if ($response === false) {
$this->_handle_error('Connection closed by server'); user_error('Connection closed by server');
return false; return false;
} }
if (empty($response)) { if (!strlen($response)) {
return ''; return '';
} }
@ -2261,7 +2275,7 @@ class Net_SSH2 {
return $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended); return $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE: //case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
default: default:
$this->_handle_error('Unable to open channel'); user_error('Unable to open channel');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
} }
break; break;
@ -2271,7 +2285,7 @@ class Net_SSH2 {
return true; return true;
//case NET_SSH2_MSG_CHANNEL_FAILURE: //case NET_SSH2_MSG_CHANNEL_FAILURE:
default: default:
$this->_handle_error('Unable to request pseudo-terminal'); user_error('Unable to request pseudo-terminal');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
} }
case NET_SSH2_MSG_CHANNEL_CLOSE: case NET_SSH2_MSG_CHANNEL_CLOSE:
@ -2333,6 +2347,8 @@ class Net_SSH2 {
$this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length); $this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
} }
case 'exit-status': case 'exit-status':
extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5)));
$this->exit_status = $exit_status;
// "The channel needs to be closed with SSH_MSG_CHANNEL_CLOSE after this message." // "The channel needs to be closed with SSH_MSG_CHANNEL_CLOSE after this message."
// -- http://tools.ietf.org/html/rfc4254#section-6.10 // -- http://tools.ietf.org/html/rfc4254#section-6.10
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
@ -2360,7 +2376,7 @@ class Net_SSH2 {
case NET_SSH2_MSG_CHANNEL_EOF: case NET_SSH2_MSG_CHANNEL_EOF:
break; break;
default: default:
$this->_handle_error('Error reading channel data'); user_error('Error reading channel data');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
} }
} }
@ -2379,7 +2395,7 @@ class Net_SSH2 {
function _send_binary_packet($data) function _send_binary_packet($data)
{ {
if (!is_resource($this->fsock) || feof($this->fsock)) { if (!is_resource($this->fsock) || feof($this->fsock)) {
$this->_handle_error('Connection closed prematurely'); user_error('Connection closed prematurely');
$this->bitmask = 0; $this->bitmask = 0;
return false; return false;
} }
@ -2675,7 +2691,7 @@ class Net_SSH2 {
$current_log = $message_log[$i]; $current_log = $message_log[$i];
$j = 0; $j = 0;
do { do {
if (!empty($current_log)) { if (strlen($current_log)) {
$output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 '; $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
} }
$fragment = $this->_string_shift($current_log, $short_width); $fragment = $this->_string_shift($current_log, $short_width);
@ -2692,7 +2708,7 @@ class Net_SSH2 {
$raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
$output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n"; $output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n";
$j++; $j++;
} while (!empty($current_log)); } while (strlen($current_log));
$output.= "\r\n"; $output.= "\r\n";
} }
@ -2886,7 +2902,7 @@ class Net_SSH2 {
padding, unsigned, and in network byte order). */ padding, unsigned, and in network byte order). */
$temp = unpack('Nlength', $this->_string_shift($signature, 4)); $temp = unpack('Nlength', $this->_string_shift($signature, 4));
if ($temp['length'] != 40) { if ($temp['length'] != 40) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -2894,7 +2910,7 @@ class Net_SSH2 {
$s = new Math_BigInteger($this->_string_shift($signature, 20), 256); $s = new Math_BigInteger($this->_string_shift($signature, 20), 256);
if ($r->compare($q) >= 0 || $s->compare($q) >= 0) { if ($r->compare($q) >= 0 || $s->compare($q) >= 0) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -2914,7 +2930,7 @@ class Net_SSH2 {
list(, $v) = $v->divide($q); list(, $v) = $v->divide($q);
if (!$v->equals($r)) { if (!$v->equals($r)) {
$this->_handle_error('Bad server signature'); user_error('Bad server signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
} }
@ -2939,7 +2955,7 @@ class Net_SSH2 {
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->loadKey(array('e' => $e, 'n' => $n), CRYPT_RSA_PUBLIC_FORMAT_RAW); $rsa->loadKey(array('e' => $e, 'n' => $n), CRYPT_RSA_PUBLIC_FORMAT_RAW);
if (!$rsa->verify($this->exchange_hash, $signature)) { if (!$rsa->verify($this->exchange_hash, $signature)) {
$this->_handle_error('Bad server signature'); user_error('Bad server signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
} }
*/ */
@ -2954,7 +2970,7 @@ class Net_SSH2 {
// also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source. // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) { if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) {
$this->_handle_error('Invalid signature'); user_error('Invalid signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -2965,12 +2981,12 @@ class Net_SSH2 {
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 3 - strlen($h)) . $h; $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 3 - strlen($h)) . $h;
if ($s != $h) { if ($s != $h) {
$this->_handle_error('Bad server signature'); user_error('Bad server signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
} }
break; break;
default: default:
$this->_handle_error('Unsupported signature format'); user_error('Unsupported signature format');
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
} }
@ -2978,20 +2994,16 @@ class Net_SSH2 {
} }
/** /**
* Error Handler * Returns the exit status of an SSH command or false.
* *
* Throws exceptions if PHPSECLIB_USE_EXCEPTIONS is defined. * @return Integer or false
* Unless PHPSECLIB_EXCEPTION_CLASS is set it'll throw generic Exceptions. * @access public
*
* @param String $string
* @access private
*/ */
function _handle_error($err_msg) { function getExitStatus()
if (defined('PHPSECLIB_USE_EXCEPTIONS') && version_compare(PHP_VERSION, '5.1.0', '>=')) { {
$class = defined('PHPSECLIB_EXCEPTION_CLASS') && class_exists(PHPSECLIB_EXCEPTION_CLASS) ? PHPSECLIB_EXCEPTION_CLASS : 'Exception'; if (is_null($this->exit_status)) {
throw(new $class($err_msg)); return false;
} else {
user_error($err_msg);
} }
return $this->exit_status;
} }
} }

View File

@ -7,10 +7,10 @@
*/ */
namespace OC\Files\Storage; namespace OC\Files\Storage;
set_include_path(get_include_path() . PATH_SEPARATOR . OC_App::getAppPath('files_external') . '/3rdparty/phpseclib/phpseclib'); set_include_path(get_include_path() . PATH_SEPARATOR . \OC_App::getAppPath('files_external') . '/3rdparty/phpseclib/phpseclib');
require('Net/SFTP.php'); require('Net/SFTP.php');
class SFTP extends OC\Files\Storage\Common { class SFTP extends \OC\Files\Storage\Common {
private $host; private $host;
private $user; private $user;
private $password; private $password;
@ -34,16 +34,16 @@ class SFTP extends OC\Files\Storage\Common {
$host_keys = $this->read_host_keys(); $host_keys = $this->read_host_keys();
$this->client = new Net_SFTP($this->host); $this->client = new \Net_SFTP($this->host);
if (!$this->client->login($this->user, $this->password)) { if (!$this->client->login($this->user, $this->password)) {
throw new Exception('Login failed'); throw new \Exception('Login failed');
} }
$current_host_key = $this->client->getServerPublicHostKey(); $current_host_key = $this->client->getServerPublicHostKey();
if (array_key_exists($this->host, $host_keys)) { if (array_key_exists($this->host, $host_keys)) {
if ($host_keys[$this->host] != $current_host_key) { if ($host_keys[$this->host] != $current_host_key) {
throw new Exception('Host public key does not match known key'); throw new \Exception('Host public key does not match known key');
} }
} else { } else {
$host_keys[$this->host] = $current_host_key; $host_keys[$this->host] = $current_host_key;
@ -53,7 +53,7 @@ class SFTP extends OC\Files\Storage\Common {
public function test() { public function test() {
if (!isset($params['host']) || !isset($params['user']) || !isset($params['password'])) { if (!isset($params['host']) || !isset($params['user']) || !isset($params['password'])) {
throw new Exception("Required parameters not set"); throw new \Exception("Required parameters not set");
} }
} }
@ -69,7 +69,7 @@ class SFTP extends OC\Files\Storage\Common {
$storage_view->getAbsolutePath('') . $storage_view->getAbsolutePath('') .
'ssh_host_keys'; 'ssh_host_keys';
} }
} catch (Exception $e) { } catch (\Exception $e) {
} }
return false; return false;
} }
@ -83,7 +83,7 @@ class SFTP extends OC\Files\Storage\Common {
} }
fclose($fp); fclose($fp);
return true; return true;
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
} }
@ -106,7 +106,7 @@ class SFTP extends OC\Files\Storage\Common {
return array_combine($hosts, $keys); return array_combine($hosts, $keys);
} }
} }
} catch (Exception $e) { } catch (\Exception $e) {
} }
return array(); return array();
} }
@ -114,7 +114,7 @@ class SFTP extends OC\Files\Storage\Common {
public function mkdir($path) { public function mkdir($path) {
try { try {
return $this->client->mkdir($this->abs_path($path)); return $this->client->mkdir($this->abs_path($path));
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
} }
@ -122,7 +122,7 @@ class SFTP extends OC\Files\Storage\Common {
public function rmdir($path) { public function rmdir($path) {
try { try {
return $this->client->delete($this->abs_path($path), true); return $this->client->delete($this->abs_path($path), true);
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
} }
@ -140,7 +140,7 @@ class SFTP extends OC\Files\Storage\Common {
} }
\OC\Files\Stream\Dir::register($id, $dir_stream); \OC\Files\Stream\Dir::register($id, $dir_stream);
return opendir('fakedir://' . $id); return opendir('fakedir://' . $id);
} catch(Exception $e) { } catch(\Exception $e) {
return false; return false;
} }
} }
@ -150,7 +150,7 @@ class SFTP extends OC\Files\Storage\Common {
$stat = $this->client->stat($this->abs_path($path)); $stat = $this->client->stat($this->abs_path($path));
if ($stat['type'] == NET_SFTP_TYPE_REGULAR) return 'file'; if ($stat['type'] == NET_SFTP_TYPE_REGULAR) return 'file';
if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) return 'dir'; if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) return 'dir';
} catch (Exeption $e) { } catch (\Exeption $e) {
} }
return false; return false;
} }
@ -166,7 +166,7 @@ class SFTP extends OC\Files\Storage\Common {
public function file_exists($path) { public function file_exists($path) {
try { try {
return $this->client->stat($this->abs_path($path)) === false ? false : true; return $this->client->stat($this->abs_path($path)) === false ? false : true;
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
} }
@ -174,7 +174,7 @@ class SFTP extends OC\Files\Storage\Common {
public function unlink($path) { public function unlink($path) {
try { try {
return $this->client->delete($this->abs_path($path), true); return $this->client->delete($this->abs_path($path), true);
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
} }
@ -191,7 +191,7 @@ class SFTP extends OC\Files\Storage\Common {
} else { } else {
$ext=''; $ext='';
} }
$tmp = OC_Helper::tmpFile($ext); $tmp = \OC_Helper::tmpFile($ext);
$this->getFile($abs_path, $tmp); $this->getFile($abs_path, $tmp);
return fopen($tmp, $mode); return fopen($tmp, $mode);
@ -212,7 +212,7 @@ class SFTP extends OC\Files\Storage\Common {
} else { } else {
$ext=''; $ext='';
} }
$tmpFile=OC_Helper::tmpFile($ext); $tmpFile=\OC_Helper::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) { if ($this->file_exists($path)) {
$this->getFile($abs_path, $tmpFile); $this->getFile($abs_path, $tmpFile);
@ -220,7 +220,7 @@ class SFTP extends OC\Files\Storage\Common {
self::$tempFiles[$tmpFile]=$abs_path; self::$tempFiles[$tmpFile]=$abs_path;
return fopen('close://'.$tmpFile, $mode); return fopen('close://'.$tmpFile, $mode);
} }
} catch (Exception $e) { } catch (\Exception $e) {
} }
return false; return false;
} }
@ -245,7 +245,7 @@ class SFTP extends OC\Files\Storage\Common {
} else { } else {
return false; return false;
} }
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
return true; return true;
@ -262,7 +262,7 @@ class SFTP extends OC\Files\Storage\Common {
public function rename($source, $target) { public function rename($source, $target) {
try { try {
return $this->client->rename($this->abs_path($source), $this->abs_path($target)); return $this->client->rename($this->abs_path($source), $this->abs_path($target));
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
} }
@ -275,10 +275,9 @@ class SFTP extends OC\Files\Storage\Common {
$size = $stat ? $stat['size'] : 0; $size = $stat ? $stat['size'] : 0;
return array('mtime' => $mtime, 'size' => $size, 'ctime' => -1); return array('mtime' => $mtime, 'size' => $size, 'ctime' => -1);
} catch (Exception $e) { } catch (\Exception $e) {
return false; return false;
} }
} }
} }
?>

View File

@ -0,0 +1,43 @@
<?php
/**
* ownCloud
*
* @author Henrik Kjölhede
* @copyright 2013 Henrik Kjölhede hkjolhede@gmail.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Test\Files\Storage;
class SFTP extends Storage {
private $config;
public function setUp() {
$id = uniqid();
$this->config = include('files_external/tests/config.php');
if ( ! is_array($this->config) or ! isset($this->config['sftp']) or ! $this->config['sftp']['run']) {
$this->markTestSkipped('SFTP backend not configured');
}
$this->config['sftp']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
$this->instance = new \OC\Files\Storage\SFTP($this->config['sftp']);
}
public function tearDown() {
if ($this->instance) {
$this->instance->rmdir('/');
}
}
}