How to retrieve digital signature information from PDF with PHP?

This is my working code in PHP7:

<?php


require_once('vendor/autoload.php');

use Sop\ASN1\Type\Constructed\Sequence;
use Sop\ASN1\Element;
use Sop\X509\Certificate\Certificate;  



$currentFile = "./upload/test2.pdf";


$content = file_get_contents($currentFile);


$regexp = '/ByteRange\ \[\s*(\d+) (\d+) (\d+)/'; // subexpressions are used to extract b and c

$result = [];
preg_match_all($regexp, $content, $result);

// $result[2][0] and $result[3][0] are b and c
if (isset($result[2]) && isset($result[3]) && isset($result[2][0]) && isset($result[3][0])) {
    $start = $result[2][0];
    $end = $result[3][0];
    if ($stream = fopen($currentFile, 'rb')) {
        $signature = stream_get_contents($stream, $end - $start - 2, $start + 1); // because we need to exclude < and > from start and end

        fclose($stream);
    }

    
    $binaryData = hex2bin($signature);
    
    $seq = Sequence::fromDER($binaryData);
    $signed_data = $seq->getTagged(0)->asExplicit()->asSequence();
    // ExtendedCertificatesAndCertificates: https://tools.ietf.org/html/rfc2315#section-6.6
    $ecac = $signed_data->getTagged(0)->asImplicit(Element::TYPE_SET)->asSet();
    // ExtendedCertificateOrCertificate: https://tools.ietf.org/html/rfc2315#section-6.5
    $ecoc = $ecac->at($ecac->count() - 1);
    $cert = Certificate::fromASN1($ecoc->asSequence());
    $commonNameValue = $cert->tbsCertificate()->subject()->toString();
    echo $commonNameValue;

    
}

Well, it's complicated (I would say even impossible, but who knows) to achieve this only with PHP.

At first, please read article about digital signature in Adobe PDF

Second, after reading this you will know that signature is stored between b and c bytes according to /ByteRange[a b c d] indicator

Third, we can extract b and c from document and then extract signature itself (guide says it will be hexdecoded PKCS7# object).

<?php

 $content = file_get_contents('test.pdf');

 $regexp = '#ByteRange\[\s*(\d+) (\d+) (\d+)#'; // subexpressions are used to extract b and c

 $result = [];
 preg_match_all($regexp, $content, $result);

 // $result[2][0] and $result[3][0] are b and c
 if (isset($result[2]) && isset($result[3]) && isset($result[2][0]) && isset($result[3][0]))
 {
     $start = $result[2][0];
     $end = $result[3][0];
     if ($stream = fopen('test.pdf', 'rb')) {
         $signature = stream_get_contents($stream, $end - $start - 2, $start + 1); // because we need to exclude < and > from start and end

         fclose($stream);
     }

     file_put_contents('signature.pkcs7', hex2bin($signature));
}

Forth, after third step we have PKCS#7 object in file signature.pkcs7. Unfortunately, I don't know methods to extract information from signature using PHP. So you must be able to run shell commands to use openssl

openssl pkcs7 -in signature.pkcs7 -inform DER -print_certs > info.txt

After running this command in file info.txt you will have a chain of certificates. Last one is the one you need. You can see the structure of the file and parse needed data.

Please also refer to this question, this question and this topic

EDIT at 2017-10-09 I knowingly advised you to see exactly this question There is a code that you can adjust to your needs.

use ASN1\Type\Constructed\Sequence;
use ASN1\Element;
use X509\Certificate\Certificate;       

$seq = Sequence::fromDER($binaryData);
$signed_data = $seq->getTagged(0)->asExplicit()->asSequence();
// ExtendedCertificatesAndCertificates: https://tools.ietf.org/html/rfc2315#section-6.6
$ecac = $signed_data->getTagged(0)->asImplicit(Element::TYPE_SET)->asSet();
// ExtendedCertificateOrCertificate: https://tools.ietf.org/html/rfc2315#section-6.5
$ecoc = $ecac->at($ecac->count() - 1);
$cert = Certificate::fromASN1($ecoc->asSequence());
$commonNameValue = $cert->tbsCertificate()->subject()->toString();
echo $commonNameValue;

I've adjusted it for you, but please make the rest by yourself.