Skip to content
This repository has been archived by the owner on May 19, 2021. It is now read-only.

Commit

Permalink
Adding getSignature().
Browse files Browse the repository at this point in the history
  • Loading branch information
kherge committed Jul 22, 2013
1 parent 6351f7a commit a591cdc
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 0 deletions.
Binary file added res/invalid.phar
Binary file not shown.
Binary file added res/md5.phar
Binary file not shown.
Binary file added res/missing.phar
Binary file not shown.
Binary file added res/openssl.phar
Binary file not shown.
4 changes: 4 additions & 0 deletions res/openssl.phar.pubkey
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKuZkrHT54KtuBCTrR36+4tibd+2un9b
aLFs3X+RHc/jDCXL8pJATz049ckfcfd2ZCMIzH1PHew8H+EMhy4CbSECAwEAAQ==
-----END PUBLIC KEY-----
Binary file added res/sha1.phar
Binary file not shown.
Binary file added res/sha256.phar
Binary file not shown.
Binary file added res/sha512.phar
Binary file not shown.
135 changes: 135 additions & 0 deletions src/lib/Herrera/Box/Box.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
use Herrera\Box\Exception\OpenSslException;
use Herrera\Box\Exception\UnexpectedValueException;
use Phar;
use PharException;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RegexIterator;
use RuntimeException;
use SplFileInfo;
use SplObjectStorage;
use Traversable;
Expand Down Expand Up @@ -44,6 +46,19 @@ class Box
*/
private $phar;

/**
* The available signature types.
*
* @var array
*/
private static $types = array(
0x01 => array('MD5', 16),
0x02 => array('SHA1', 20),
0x03 => array('SHA256', 32),
0x04 => array('SHA512', 64),
0x10 => array('OpenSSL', null),
);

/**
* The placeholder values.
*
Expand Down Expand Up @@ -254,6 +269,71 @@ public function getPhar()
return $this->phar;
}

/**
* Returns the signature of the phar.
*
* This method does not use the extension to extract the phar's signature.
*
* @param string $path The phar file path.
*
* @return array The signature.
*
* @throws PharException If the phar is not valid.
* @throws RuntimeException If the file could not be read.
*/
public static function getSignature($path)
{
$signature = array();

$raw = self::readEnd($path, -12, 12);

$flag = substr($raw, -4, 4);

$type = unpack('V', substr($raw, -8, 4));
$type = $type[1];

$size = unpack('V', substr($raw, 0, 4));
$size = $size[1];

if ('GBMB' === $flag) {
if (isset(self::$types[$type])) {
$signature['hash_type'] = self::$types[$type][0];

if (self::$types[$type][1]) {
$size = self::$types[$type][1];
}

$signature['hash'] = self::readEnd(
$path,
self::$types[$type][1] ? -8 - $size : -12 - $size,
$size
);

$signature['hash'] = unpack('H*', $signature['hash']);
$signature['hash'] = strtoupper($signature['hash'][1]);
} else {
throw new PharException(
sprintf(
'The signature type (%x) of "%s" is not recognized.',
$type,
$path
)
);
}
} else {
if (ini_get('phar.require_hash')) {
throw new PharException(
sprintf(
'The phar "%s" is not signed.',
$path
)
);
}
}

return $signature;
}

/**
* Replaces the placeholders with their values.
*
Expand Down Expand Up @@ -392,4 +472,59 @@ public function signUsingFile($file, $password = null)

$this->sign($key, $password);
}

/**
* Reads from the end of a file.
*
* @param string $file The file handle.
* @param integer $offset The end offset.
* @param integer $bytes The number of bytes to read.
*
* @return string The read bytes.
*
* @throws RuntimeException If the file could not be read.
*/
private static function readEnd($file, $offset, $bytes)
{
if (false === ($size = @filesize($file))) {
$error = error_get_last();

throw new RuntimeException(
sprintf(
'The size of the file "%s" could not be retrieved: %s',
$file,
$error['message']
)
);
}

$read = @file_get_contents($file, false, null, $size + $offset, $bytes);

if (false === $read) {
$error = error_get_last();

throw new RuntimeException(
sprintf(
'The file "%s" could not be read at offset %d for %d bytes: %s',
$file,
$size + $offset,
$bytes,
$error['message']
)
);
}

if (($actual = strlen($read)) !== $bytes) {
throw new RuntimeException(
sprintf(
'Could only read %d of %d bytes from "%s".',
$actual,
$bytes,
$file
)
);
}

return $read;
}
}
71 changes: 71 additions & 0 deletions src/tests/Herrera/Box/Tests/BoxTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,37 @@ public function getPrivateKey()
);
}

public function getSignatures()
{
return array(
array(
RES_DIR . '/md5.phar',
'MD5',
'6772FC5AB8AB8D72BB69B6A0C323C796'
),
array(
RES_DIR . '/sha1.phar',
'SHA1',
'A158DF4720C619E84A777982402B5D32394805E5'
),
array(
RES_DIR . '/sha256.phar',
'SHA256',
'D0A6AB31437CA8485779E7603670ABDE05C911EA7FCEC051B8D3FB14A1480B7D'
),
array(
RES_DIR . '/sha512.phar',
'SHA512',
'B4CAE177138A773283A748C8770A7142F0CC36D6EE88E37900BCF09A92D840D237CE3F3B47C2C7B39AC2D2C0F9A16D63FE70E1A455723DD36840B6E2E64E2130'
),
array(
RES_DIR . '/openssl.phar',
'OpenSSL',
'54AF1D4E5459D3A77B692E46FDB9C965D1C7579BD1F2AD2BECF4973677575444FE21E104B7655BA3D088090C28DF63D14876B277C423C8BFBCDB9E3E63F9D61A'
),
);
}

public function testAddCompactor()
{
$compactor = new Compactor();
Expand Down Expand Up @@ -319,6 +350,46 @@ public function testGetPhar()
$this->assertSame($this->phar, $this->box->getPhar());
}

/**
* @dataProvider getSignatures
*/
public function testGetSignature($file, $type, $hash)
{
$signature = Box::getSignature($file);

$this->assertEquals(
array(
'hash_type' => $type,
'hash' => $hash,
),
$signature
);
}

public function testGetSignatureInvalid()
{
$path = RES_DIR . '/invalid.phar';

$this->setExpectedException(
'PharException',
"The signature type (ffffffff) of \"$path\" is not recognized."
);

Box::getSignature($path);
}

public function testGetSignatureMissing()
{
$path = RES_DIR . '/missing.phar';

$this->setExpectedException(
'PharException',
"The phar \"$path\" is not signed."
);

Box::getSignature($path);
}

public function testReplaceValues()
{
$this->setPropertyValue(
Expand Down

0 comments on commit a591cdc

Please sign in to comment.