diff --git a/lib/Handler/Pkcs12Handler.php b/lib/Handler/Pkcs12Handler.php index eca93632a..33cef3400 100644 --- a/lib/Handler/Pkcs12Handler.php +++ b/lib/Handler/Pkcs12Handler.php @@ -87,20 +87,33 @@ public function readCertificate(string $uid, string $privateKey): array { */ private function getSignatures($resource): iterable { $content = stream_get_contents($resource); - preg_match_all('/ByteRange\s*\[(\d+) (?\d+) (?\d+) (\d+)?/', $content, $bytes); - if (empty($bytes['start']) || empty($bytes['end'])) { + preg_match_all( + '/ByteRange\s*\[\s*(?\d+)\s+(?\d+)\s+(?\d+)\s+(?\d+)\s*\]/', + $content, + $bytes + ); + if (empty($bytes['offset1']) || empty($bytes['length1']) || empty($bytes['offset2']) || empty($bytes['length2'])) { throw new LibresignException($this->l10n->t('Unsigned file.')); } - for ($i = 0; $i < count($bytes['start']); $i++) { + for ($i = 0; $i < count($bytes['offset1']); $i++) { + // Starting position (in bytes) of the first part of the PDF that will be included in the validation. + $offset1 = (int)$bytes['offset1'][$i]; + // Length (in bytes) of the first part. + $length1 = (int)$bytes['length1'][$i]; + // Starting position (in bytes) of the second part, immediately after the signature. + $offset2 = (int)$bytes['offset2'][$i]; + + $signatureStart = $offset1 + $length1 + 1; + $signatureLength = $offset2 - $signatureStart - 1; + rewind($resource); - $signature = stream_get_contents( - $resource, - $bytes['end'][$i] - $bytes['start'][$i] - 2, - $bytes['start'][$i] + 1 - ); + + $signature = stream_get_contents($resource, $signatureLength, $signatureStart); + yield hex2bin($signature); } + $this->tempManager->clean(); } @@ -113,6 +126,7 @@ public function getCertificateChain($resource): array { $signerCounter = 0; $certificates = []; foreach ($this->getSignatures($resource) as $signature) { + // The signature could be invalid if (!$signature) { continue; }