- fixed a bug that prevented multi-prime RSA keys from loading

- slightly refactored Random.php
- implemented RSA blinding


git-svn-id: http://phpseclib.svn.sourceforge.net/svnroot/phpseclib/trunk@93 21d32557-59b3-4da0-833f-c5933fad653e
This commit is contained in:
Jim Wigginton 2010-02-28 05:28:38 +00:00
parent 1a2b6e1087
commit 695207246a
2 changed files with 90 additions and 47 deletions

View File

@ -62,7 +62,7 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMIX Jim Wigginton * @copyright MMIX Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt * @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: RSA.php,v 1.11 2010-02-26 03:40:25 terrafrost Exp $ * @version $Id: RSA.php,v 1.12 2010-02-28 05:28:38 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -877,8 +877,9 @@ class Crypt_RSA {
$this->_string_shift($key); $this->_string_shift($key);
$length = $this->_decodeLength($key); $length = $this->_decodeLength($key);
$components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), -256)); $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), -256));
if (!empty($key)) { if (!empty($key)) {
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
return false; return false;
} }
$this->_decodeLength($key); $this->_decodeLength($key);
@ -1286,31 +1287,86 @@ class Crypt_RSA {
} }
$num_primes = count($this->primes); $num_primes = count($this->primes);
$m_i = array(
1 => $x->modPow($this->exponents[1], $this->primes[1]),
2 => $x->modPow($this->exponents[2], $this->primes[2])
);
$h = $m_i[1]->subtract($m_i[2]);
$h = $h->multiply($this->coefficients[2]);
list(, $h) = $h->divide($this->primes[1]);
$m = $m_i[2]->add($h->multiply($this->primes[2]));
$r = $this->primes[1]; if (defined('CRYPT_RSA_DISABLE_BLINDING')) {
for ($i = 3; $i <= $num_primes; $i++) { $m_i = array(
$m_i = $x->modPow($this->exponents[$i], $this->primes[$i]); 1 => $x->modPow($this->exponents[1], $this->primes[1]),
2 => $x->modPow($this->exponents[2], $this->primes[2])
);
$h = $m_i[1]->subtract($m_i[2]);
$h = $h->multiply($this->coefficients[2]);
list(, $h) = $h->divide($this->primes[1]);
$m = $m_i[2]->add($h->multiply($this->primes[2]));
$r = $r->multiply($this->primes[$i - 1]); $r = $this->primes[1];
for ($i = 3; $i <= $num_primes; $i++) {
$m_i = $x->modPow($this->exponents[$i], $this->primes[$i]);
$h = $m_i->subtract($m); $r = $r->multiply($this->primes[$i - 1]);
$h = $h->multiply($this->coefficients[$i]);
list(, $h) = $h->divide($this->primes[$i]);
$m = $m->add($r->multiply($h)); $h = $m_i->subtract($m);
$h = $h->multiply($this->coefficients[$i]);
list(, $h) = $h->divide($this->primes[$i]);
$m = $m->add($r->multiply($h));
}
} else {
$m_i = array(
1 => $this->_blind($x, 1),
2 => $this->_blind($x, 2)
);
$h = $m_i[1]->subtract($m_i[2]);
$h = $h->multiply($this->coefficients[2]);
list(, $h) = $h->divide($this->primes[1]);
$m = $m_i[2]->add($h->multiply($this->primes[2]));
$r = $this->primes[1];
for ($i = 3; $i <= $num_primes; $i++) {
$m_i = $this->_blind($x, $i);
$r = $r->multiply($this->primes[$i - 1]);
$h = $m_i->subtract($m);
$h = $h->multiply($this->coefficients[$i]);
list(, $h) = $h->divide($this->primes[$i]);
$m = $m->add($r->multiply($h));
}
} }
return $m; return $m;
} }
/**
* Performs RSA Blinding
*
* Protects against timing attacks by employing RSA Blinding.
* Returns $x->modPow($this->exponents[$i], $this->primes[$i])
*
* @access private
* @param Math_BigInteger $x
* @param Integer $i
* @return Math_BigInteger
*/
function _blind($x, $i)
{
static $one;
if (!isset($one)) {
$one = new Math_BigInteger(1);
}
$r = $one->random($one, $this->primes[$i]->subtract($one));
$x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i]));
$x = $x->modPow($this->exponents[$i], $this->primes[$i]);
$r = $r->modInverse($this->primes[$i]);
$x = $x->multiply($r);
list(, $x) = $x->divide($this->primes[$i]);
return $x;
}
/** /**
* RSAEP * RSAEP
* *
@ -1886,7 +1942,7 @@ class Crypt_RSA {
// Compare // Compare
return $em == $em2; return $em === $em2;
} }
/** /**

View File

@ -35,7 +35,7 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt * @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: Random.php,v 1.5 2010-02-19 22:39:44 terrafrost Exp $ * @version $Id: Random.php,v 1.6 2010-02-28 05:28:38 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -56,6 +56,10 @@
*/ */
function crypt_random($min = 0, $max = 0x7FFFFFFF) function crypt_random($min = 0, $max = 0x7FFFFFFF)
{ {
if ($min == $max) {
return $min;
}
// see http://en.wikipedia.org/wiki//dev/random // see http://en.wikipedia.org/wiki//dev/random
if (file_exists('/dev/urandom')) { if (file_exists('/dev/urandom')) {
$fp = fopen('/dev/urandom', 'rb'); $fp = fopen('/dev/urandom', 'rb');
@ -89,47 +93,30 @@ function crypt_random($min = 0, $max = 0x7FFFFFFF)
// in the browser and reloading the page. // in the browser and reloading the page.
if (!isset($crypto)) { if (!isset($crypto)) {
$key = $iv = '';
for ($i = 0; $i < 8; $i++) {
$key.= pack('n', mt_rand(0, 0xFFFF));
$iv .= pack('n', mt_rand(0, 0xFFFF));
}
switch (true) { switch (true) {
case class_exists('Crypt_AES'): case class_exists('Crypt_AES'):
$key = $iv = '';
for ($i = 0; $i < 8; $i++) {
$key.= pack('n', mt_rand(0, 0xFFFF));
$iv .= pack('n', mt_rand(0, 0xFFFF));
}
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
$crypto->setKey($key);
$crypto->setIV($iv);
break; break;
case class_exists('Crypt_TripleDES'): case class_exists('Crypt_TripleDES'):
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
break;
case class_exists('Crypt_DES'): case class_exists('Crypt_DES'):
$key = $iv = ''; $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
for ($i = 0; $i < 4; $i++) {
$key.= pack('n', mt_rand(0, 0xFFFF));
$iv .= pack('n', mt_rand(0, 0xFFFF));
}
if (class_exists('Crypt_TripleDES')) {
for ($i = 0; $i < 4; $i++) {
$key.= pack('n', mt_rand(0, 0xFFFF));
}
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
} else {
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
}
$crypto->setKey($key);
$crypto->setIV($iv);
break; break;
case class_exists('Crypt_RC4'): case class_exists('Crypt_RC4'):
$key = '';
for ($i = 0; $i < 8; $i++) {
$key.= pack('n', mt_rand(0, 0xFFFF));
}
$crypto = new Crypt_RC4(); $crypto = new Crypt_RC4();
$crypto->setKey($key);
break; break;
default: default:
extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF))))); extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF)))));
return abs($random) % ($max - $min) + $min; return abs($random) % ($max - $min) + $min;
} }
$crypto->setKey($key);
$crypto->setIV($iv);
} }
extract(unpack('Nrandom', $crypto->encrypt("\0\0\0\0"))); extract(unpack('Nrandom', $crypto->encrypt("\0\0\0\0")));