Completed
Pull Request — master (#9)
by Carlos C
03:14
created

DocumentSigner::createDocumentToSign()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 8
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 10
ccs 9
cts 9
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpCfdi\Finkok\Helpers;
6
7
use DateTimeImmutable;
8
use DOMDocument;
9
use LogicException;
10
use PhpCfdi\Credentials\Credential;
11
use RobRichards\XMLSecLibs\XMLSecurityDSig;
12
use RobRichards\XMLSecLibs\XMLSecurityKey;
13
14
class DocumentSigner
15
{
16
    /** @var string */
17
    private $rfc;
18
19
    /** @var DateTimeImmutable */
20
    private $date;
21
22
    /** @var string */
23
    private $content;
24
25 2
    public function __construct(string $rfc, DateTimeImmutable $date, string $content)
26
    {
27 2
        $this->rfc = $rfc;
28 2
        $this->date = $date;
29 2
        $this->content = $content;
30 2
    }
31
32 1
    public function rfc(): string
33
    {
34 1
        return $this->rfc;
35
    }
36
37 1
    public function date(): DateTimeImmutable
38
    {
39 1
        return $this->date;
40
    }
41
42 1
    public function content(): string
43
    {
44 1
        return $this->content;
45
    }
46
47 1
    public function sign(string $certificateFile, string $privateKeyFile, string $passPhrase): string
48
    {
49 1
        $credential = Credential::openFiles($certificateFile, $privateKeyFile, $passPhrase);
50 1
        return $this->signUsingCredential($credential);
51
    }
52
53 1
    public function signUsingCredential(Credential $credential): string
54
    {
55 1
        $document = $this->createDocumentToSign();
56 1
        $this->signDocumentUsingCredential($document, $credential);
57 1
        return $document->saveXML();
58
    }
59
60 1
    public function createDocumentToSign(): DOMDocument
61
    {
62 1
        $document = new DOMDocument('1.0', 'UTF-8');
63 1
        $root = $document->createElement('documento');
64 1
        $document->appendChild($root);
65 1
        $contract = $document->createElement('contrato', $this->content());
66 1
        $contract->setAttribute('rfc', $this->rfc());
67 1
        $contract->setAttribute('fecha', $this->date()->format('Y-m-d\TH:i:s'));
68 1
        $root->appendChild($contract);
69 1
        return $document;
70
    }
71
72 2
    public function signDocumentUsingCredential(DOMDocument $document, Credential $credential): void
73
    {
74 2
        $root = $document->documentElement;
75 2
        if (null === $root) {
76 1
            throw new LogicException('The DOM Document does not contains a root element');
77
        }
78 1
        $objDSig = new XMLSecurityDSig();
79 1
        $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
80 1
        $objDSig->addReference(
81 1
            $document,
82 1
            XMLSecurityDSig::SHA1,
83 1
            ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],
84 1
            ['force_uri' => true]
85
        );
86
87 1
        $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, ['type' => 'private']);
88 1
        $objKey->passphrase = $credential->privateKey()->passPhrase(); // set passphrase before loading key
89 1
        $objKey->loadKey($credential->privateKey()->pem(), false, false);
90
91 1
        $objDSig->sign($objKey);
92 1
        $objDSig->add509Cert($credential->certificate()->pem(), true, false);
93
94 1
        $objDSig->appendSignature($root);
95 1
    }
96
}
97