add corrupted jar and start working on jar signing parsing
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
2b9ff0d04c
commit
b3180f70e0
5 changed files with 101 additions and 26 deletions
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace CubiStore\Web\Utils;
|
||||
|
||||
class APKSignatureInfo
|
||||
{
|
||||
/**
|
||||
* Which version of signature is used 1, 2, and 3 exist
|
||||
* 1. uses JAR Signing
|
||||
* 2. uses APK Signature Scheme
|
||||
* 3. extended APK Signature Scheme
|
||||
* @var int
|
||||
*/
|
||||
public $version;
|
||||
public $signer;
|
||||
public $signature;
|
||||
}
|
||||
|
|
@ -10,15 +10,21 @@ class ApkSignUtils
|
|||
const ZIP_END_OF_CENTRAL_DIRECTORY_RECORD = "PK\x05\x06";
|
||||
const ZIP_CENTRAL_DIRECTORY_RECORD = "PK\x01\x02";
|
||||
|
||||
const ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_LOCATOR = "PK\x07\x06";
|
||||
const ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_LOCATOR = "PK\x06\x07";
|
||||
const ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD = "PK\x06\x06";
|
||||
|
||||
public static function findSignature($file)
|
||||
public static function findSignature($file): ?ApkSignatureInfo
|
||||
{
|
||||
self::tryAPKSignatureV2($file);
|
||||
$signature = self::tryAPKSignatureV2($file);
|
||||
|
||||
if ($signature !== null) {
|
||||
return $signature;
|
||||
}
|
||||
|
||||
return self::tryJARSignature($file);
|
||||
}
|
||||
|
||||
public static function tryAPKSignatureV2($file)
|
||||
public static function tryAPKSignatureV2($file): ?ApkSignatureInfo
|
||||
{
|
||||
// APK Signature Block is located -before- the Central Directory Record
|
||||
// Try finding offset of that
|
||||
|
|
@ -42,11 +48,13 @@ class ApkSignUtils
|
|||
|
||||
if (substr($data, 8) === "APK Sig Block 42") {
|
||||
$blockSize = Bytes::readUint8LE($data);
|
||||
static::readAPKSignatureInfo($fh, $offset - $blockSize, $blockSize);
|
||||
return static::readAPKSignatureInfo($fh, $offset - $blockSize, $blockSize);
|
||||
}
|
||||
} finally {
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function findStartOfCentralDirectoryRecord($file): int
|
||||
|
|
@ -197,7 +205,7 @@ class ApkSignUtils
|
|||
|
||||
$zip64Offset = Bytes::readUint8LE($zip64EOCD, 48);
|
||||
|
||||
if ($legacyOffset !== 2 * 32 && $legacyOffset != $zip64Offset) {
|
||||
if ($legacyOffset !== 2 ** 32 && $legacyOffset !== $zip64Offset) {
|
||||
throw new RuntimeException("Corrupted ZIP, ZIP64 offset and normal offset don't match up.");
|
||||
}
|
||||
|
||||
|
|
@ -206,7 +214,50 @@ class ApkSignUtils
|
|||
return true;
|
||||
}
|
||||
|
||||
private static function readAPKSignatureInfo($fh, int $offset, int $size)
|
||||
private static function readAPKSignatureInfo($fh, int $offset, int $size): ?ApkSignatureInfo
|
||||
{
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function tryJARSignature($file)
|
||||
{
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($file) !== true) {
|
||||
throw new RuntimeException("Failed to open APK");
|
||||
}
|
||||
|
||||
$manifest = $zip->getFromName("META-INF/MANIFEST.MF");
|
||||
|
||||
if ($manifest === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$found = false;
|
||||
$entryName = "";
|
||||
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||
$entryStat = $zip->statIndex($i);
|
||||
if ($entryStat === false || !isset($entryStat['name'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$entryName = $entryStat['name'];
|
||||
|
||||
if (!preg_match("~^META-INF/[^\/]+\.SF$~", $entryName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$found = true;
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$signManifest = $zip->getFromName($entryName);
|
||||
|
||||
if ($signManifest === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
34
src/Utils/ApkSignatureInfo.php
Normal file
34
src/Utils/ApkSignatureInfo.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace CubiStore\Web\Utils;
|
||||
|
||||
class ApkSignatureInfo
|
||||
{
|
||||
/**
|
||||
* Which version of signature is used 1, 2, and 3 exist
|
||||
* 1. uses JAR Signing
|
||||
* 2. uses APK Signature Scheme
|
||||
* 3. extended APK Signature Scheme
|
||||
* @var int
|
||||
*/
|
||||
public $version;
|
||||
public $signer;
|
||||
|
||||
/**
|
||||
* As taken from the fdroidserver code:
|
||||
*
|
||||
* This uses a strange algorithm that was devised at the very
|
||||
* beginning of F-Droid. Since it is only used for checking
|
||||
* signature compatibility, it does not matter much that it uses MD5.
|
||||
*
|
||||
* To get the same MD5 has that fdroidclient gets, we encode the .RSA
|
||||
* certificate in a specific format and pass it hex-encoded to the
|
||||
* md5 digest algorithm. This is not the same as the standard X.509
|
||||
* certificate fingerprint.
|
||||
*
|
||||
* @link https://gitlab.com/fdroid/fdroidserver/blob/master/fdroidserver/update.py#L418
|
||||
* @var string
|
||||
*/
|
||||
public $fdroidSignerSignature;
|
||||
}
|
||||
|
|
@ -9,9 +9,17 @@ use PHPUnit\Framework\TestCase;
|
|||
|
||||
class ApkSignUtilsTest extends TestCase
|
||||
{
|
||||
function testCorruptedZip64() {
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage("Corrupted ZIP, ZIP64 offset and normal offset don't match up.");
|
||||
$utils = new ApkSignUtils();
|
||||
$utils->findSignature(__DIR__ . '/../../var/testdata/signedapks/zip64corrupted.jar');
|
||||
}
|
||||
|
||||
function testSha1Signature()
|
||||
{
|
||||
$utils = new ApkSignUtils();
|
||||
$utils->findSignature(__DIR__ . '/../../var/testdata/signedapks/apksignv2.apk');
|
||||
$apkSignature = $utils->findSignature(__DIR__ . '/../../var/testdata/signedapks/sha1.apk');
|
||||
$this->assertNotNull($apkSignature, "Couldn't find APK signature");
|
||||
}
|
||||
}
|
||||
BIN
var/testdata/signedapks/zip64corrupted.jar
vendored
Normal file
BIN
var/testdata/signedapks/zip64corrupted.jar
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue