From 05da12e6c0611b8dcefc8b208b129853d7c34a99 Mon Sep 17 00:00:00 2001 From: Kevin Herrera Date: Tue, 23 Jul 2013 10:27:25 -0700 Subject: [PATCH] Using new signature classes. --- src/lib/Herrera/Box/Signature.php | 78 +++++-------------- src/tests/Herrera/Box/Tests/SignatureTest.php | 71 +++++++++++++---- 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/src/lib/Herrera/Box/Signature.php b/src/lib/Herrera/Box/Signature.php index 04697c0..c083a80 100644 --- a/src/lib/Herrera/Box/Signature.php +++ b/src/lib/Herrera/Box/Signature.php @@ -5,6 +5,7 @@ use Herrera\Box\Exception\Exception; use Herrera\Box\Exception\FileException; use Herrera\Box\Exception\OpenSslException; +use Herrera\Box\Signature\VerifyInterface; use PharException; /** @@ -48,27 +49,32 @@ class Signature array( 'name' => 'MD5', 'flag' => 0x01, - 'size' => 16 + 'size' => 16, + 'class' => 'Herrera\\Box\\Signature\\Hash' ), array( 'name' => 'SHA-1', 'flag' => 0x02, - 'size' => 20 + 'size' => 20, + 'class' => 'Herrera\\Box\\Signature\\Hash' ), array( 'name' => 'SHA-256', 'flag' => 0x03, - 'size' => 32 + 'size' => 32, + 'class' => 'Herrera\\Box\\Signature\\Hash' ), array( 'name' => 'SHA-512', 'flag' => 0x04, - 'size' => 64 + 'size' => 64, + 'class' => 'Herrera\\Box\\Signature\\Hash' ), array( 'name' => 'OpenSSL', 'flag' => 0x10, - 'size' => null + 'size' => null, + 'class' => 'Herrera\\Box\\Signature\\PublicKeyDelegate' ), ); @@ -147,7 +153,7 @@ public function get($required = null) ); } - return; + return null; } $this->seek(-8, SEEK_END); @@ -231,53 +237,9 @@ public function verify() $this->seek(0); - if (0x10 === $type['flag']) { - if (!extension_loaded('openssl')) { - throw OpenSslException::create( - 'The "openssl" extension is required to verify signatures using a public key.' - ); - } - $file = $this->file . '.pubkey'; - - if (false === ($key = @file_get_contents($file))) { - throw FileException::lastError(); - } - - /* - * At the moment, there doesn't seem to be an efficient way of - * generating a progressive hash without resorting to using both - * "openssl" and "phar" extensions. - */ - OpenSslException::reset(); - - ob_start(); - - $result = openssl_verify( - $this->read($size), - pack('H*', $signature['hash']), - $key - ); - - $error = trim(ob_get_clean()); - - if (-1 === $result) { - throw OpenSslException::lastError(); - } elseif (!empty($error)) { - throw new OpenSslException($error); - } - - return (1 === $result); - } - - $context = @hash_init( - strtolower( - preg_replace('/\-/', '', $signature['hash_type']) - ) - ); - - if (false === $context) { - throw Exception::lastError(); - } + /** @var $verify VerifyInterface */ + $verify = new $type['class'](); + $verify->init($type['name'], $this->file); $buffer = 64; @@ -287,14 +249,12 @@ public function verify() $size = 0; } - hash_update($context, $this->read($buffer)); + $verify->update($this->read($buffer)); $size -= $buffer; } - $hash = strtoupper(hash_final($context)); - - return ($signature['hash'] === $hash); + return $verify->verify($signature['hash']); } /** @@ -303,7 +263,7 @@ public function verify() private function close() { if ($this->handle) { - fclose($this->handle); + @fclose($this->handle); $this->handle = null; } @@ -342,7 +302,7 @@ private function handle() */ private function read($bytes) { - if (false === ($read = fread($this->handle(), $bytes))) { + if (false === ($read = @fread($this->handle(), $bytes))) { throw FileException::lastError(); } diff --git a/src/tests/Herrera/Box/Tests/SignatureTest.php b/src/tests/Herrera/Box/Tests/SignatureTest.php index 6dd82bf..e14fd17 100644 --- a/src/tests/Herrera/Box/Tests/SignatureTest.php +++ b/src/tests/Herrera/Box/Tests/SignatureTest.php @@ -10,6 +10,8 @@ class SignatureTest extends TestCase { + private $types; + public function getPhars() { return array( @@ -114,36 +116,77 @@ public function testVerify($path) $this->assertTrue($sig->verify()); } - public function testVerifyMissingKey() - { - $dir = $this->createDir(); + // private methods - copy(RES_DIR . '/openssl.phar', "$dir/openssl.phar"); + public function testHandle() + { + $sig = new Signature(__FILE__); - $sig = new Signature("$dir/openssl.phar"); + $this->setPropertyValue($sig, 'file', '/does/not/exist'); $this->setExpectedException( 'Herrera\\Box\\Exception\\FileException', 'No such file or directory' ); - $sig->verify(); + $this->callMethod($sig, 'handle'); } - public function testVerifyErrorHandlingBug() + public function testRead() { - $dir = $this->createDir(); + $sig = new Signature(__FILE__); + + $this->setPropertyValue($sig, 'handle', true); - copy(RES_DIR . '/openssl.phar', "$dir/openssl.phar"); - touch("$dir/openssl.phar.pubkey"); + $this->setExpectedException( + 'Herrera\\Box\\Exception\\FileException', + 'boolean given' + ); - $sig = new Signature("$dir/openssl.phar"); + $this->callMethod($sig, 'read', array(123)); + } + + public function testReadShort() + { + $file = $this->createFile(); + $sig = new Signature($file); $this->setExpectedException( - 'Herrera\\Box\\Exception\\OpenSslException', - 'cannot be coerced' + 'Herrera\\Box\\Exception\\FileException', + "Only read 0 of 1 bytes from \"$file\"." + ); + + $this->callMethod($sig, 'read', array(1)); + } + + public function testSeek() + { + $file = $this->createFile(); + $sig = new Signature($file); + + $this->setExpectedException( + 'Herrera\\Box\\Exception\\FileException' + ); + + $this->callMethod($sig, 'seek', array(-1)); + } + + protected function setUp() + { + $this->types = $this->getPropertyValue( + 'Herrera\\Box\\Signature', + 'types' + ); + } + + protected function tearDown() + { + $this->setPropertyValue( + 'Herrera\\Box\\Signature', + 'types', + $this->types ); - $sig->verify(); + parent::tearDown(); } }