| 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 | 6 |  |     public function __construct(string $rfc, DateTimeImmutable $date, string $content) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 | 6 |  |         $this->rfc = $rfc; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 | 6 |  |         $this->date = $date; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 | 6 |  |         $this->content = $content; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 31 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 32 | 5 |  |     public function rfc(): string | 
            
                                                                        
                            
            
                                    
            
            
                | 33 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 34 | 5 |  |         return $this->rfc; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 | 5 |  |     public function date(): DateTimeImmutable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 5 |  |         return $this->date; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 | 5 |  |     public function content(): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 | 5 |  |         return $this->content; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 | 4 |  |     public function sign(string $certificateFile, string $privateKeyFile, string $passPhrase): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 | 4 |  |         $credential = Credential::openFiles($certificateFile, $privateKeyFile, $passPhrase); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 | 4 |  |         return $this->signUsingCredential($credential); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 | 5 |  |     public function signUsingCredential(Credential $credential): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 | 5 |  |         $document = $this->createDocumentToSign(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 | 5 |  |         $this->signDocumentUsingCredential($document, $credential); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 | 5 |  |         return strval($document->saveXML()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 5 |  |     public function createDocumentToSign(): DOMDocument | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 5 |  |         $document = new DOMDocument('1.0', 'UTF-8'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 | 5 |  |         $root = $document->createElement('documento'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 | 5 |  |         $document->appendChild($root); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 5 |  |         $contract = $document->createElement('contrato', $this->content()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 | 5 |  |         $contract->setAttribute('rfc', $this->rfc()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 5 |  |         $contract->setAttribute('fecha', $this->date()->format('Y-m-d\TH:i:s')); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 5 |  |         $root->appendChild($contract); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 | 5 |  |         return $document; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 6 |  |     public function signDocumentUsingCredential(DOMDocument $document, Credential $credential): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 | 6 |  |         $root = $document->documentElement; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 6 |  |         if (null === $root) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 1 |  |             throw new LogicException('The DOM Document does not contains a root element'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 5 |  |         $objDSig = new XMLSecurityDSig(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 | 5 |  |         $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 | 5 |  |         $objDSig->addReference( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 5 |  |             $document, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 5 |  |             XMLSecurityDSig::SHA1, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 5 |  |             ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 5 |  |             ['force_uri' => true] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 | 5 |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 | 5 |  |         $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, ['type' => 'private']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 | 5 |  |         $objKey->passphrase = $credential->privateKey()->passPhrase(); // set passphrase before loading key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 | 5 |  |         $objKey->loadKey($credential->privateKey()->pem(), false, false); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 5 |  |         $objDSig->sign($objKey); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 5 |  |         $objDSig->add509Cert($credential->certificate()->pem(), true, false); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 5 |  |         $objDSig->appendSignature($root); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 96 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 97 |  |  |  |