From 5ec389c91c3aa3a0e5a8622ff3e6156b4d49d657 Mon Sep 17 00:00:00 2001 From: Gerson Felipe Schwinn Date: Mon, 1 Jul 2024 18:37:22 -0300 Subject: [PATCH 1/4] =?UTF-8?q?Criando=20classe=20para=20permitir=20m?= =?UTF-8?q?=C3=BAltiplas=20assinaturas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Signer.php | 28 ++++++++++++++-------------- src/SignerMulti.php | 37 +++++++++++++++++++++++++++++++++++++ tests/SignerMultiTest.php | 22 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 14 deletions(-) create mode 100755 src/SignerMulti.php create mode 100755 tests/SignerMultiTest.php diff --git a/src/Signer.php b/src/Signer.php index 4cb5dc1..e66e719 100755 --- a/src/Signer.php +++ b/src/Signer.php @@ -74,8 +74,8 @@ public static function sign( if (empty($node) || empty($root)) { throw SignerException::tagNotFound($tagname); } - if (!self::existsSignature($content)) { - $dom = self::createSignature( + if (!static::existsSignature($content)) { + $dom = static::createSignature( $certificate, $dom, $root, @@ -100,7 +100,7 @@ public static function sign( * @param array $canonical parameters to format node for signature (opcional) * @return \DOMDocument */ - private static function createSignature( + protected static function createSignature( Certificate $certificate, DOMDocument $dom, DOMNode $root, @@ -123,7 +123,7 @@ private static function createSignature( $nsTransformMethod1 = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'; $nsTransformMethod2 = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'; $idSigned = trim($node->getAttribute($mark)); - $digestValue = self::makeDigest($node, $digestAlgorithm, $canonical); + $digestValue = static::makeDigest($node, $digestAlgorithm, $canonical); $signatureNode = $dom->createElementNS($nsDSIG, 'Signature'); $root->appendChild($signatureNode); $signedInfoNode = $dom->createElement('SignedInfo'); @@ -153,7 +153,7 @@ private static function createSignature( $digestMethodNode->setAttribute('Algorithm', $nsDigestMethod); $digestValueNode = $dom->createElement('DigestValue', $digestValue); $referenceNode->appendChild($digestValueNode); - $c14n = self::canonize($signedInfoNode, $canonical); + $c14n = static::canonize($signedInfoNode, $canonical); $signature = $certificate->sign($c14n, $algorithm); $signatureValue = base64_encode($signature); $signatureValueNode = $dom->createElement('SignatureValue', $signatureValue); @@ -181,7 +181,7 @@ private static function createSignature( */ public static function removeSignature($content) { - if (!self::existsSignature($content)) { + if (!static::existsSignature($content)) { return $content; } $dom = new \DOMDocument('1.0', 'utf-8'); @@ -206,13 +206,13 @@ public static function removeSignature($content) */ public static function isSigned($content, $tagname = '', $canonical = self::CANONICAL) { - if (!self::existsSignature($content)) { + if (!static::existsSignature($content)) { return false; } - if (!self::digestCheck($content, $tagname, $canonical)) { + if (!static::digestCheck($content, $tagname, $canonical)) { return false; } - return self::signatureCheck($content, $canonical); + return static::signatureCheck($content, $canonical); } /** @@ -254,7 +254,7 @@ public static function signatureCheck($xml, $canonical = self::CANONICAL) } $certificateContent = $signature->getElementsByTagName('X509Certificate')->item(0)->nodeValue; $publicKey = PublicKey::createFromContent($certificateContent); - $signInfoNode = self::canonize($signature->getElementsByTagName('SignedInfo')->item(0), $canonical); + $signInfoNode = static::canonize($signature->getElementsByTagName('SignedInfo')->item(0), $canonical); $signatureValue = $signature->getElementsByTagName('SignatureValue')->item(0)->nodeValue; $decodedSignature = base64_decode(str_replace(array("\r", "\n"), '', $signatureValue)); if (!$publicKey->verify($signInfoNode, $decodedSignature, $algorithm)) { @@ -305,7 +305,7 @@ public static function digestCheck($xml, $tagname = '', $canonical = self::CANON if ($sigURI == '') { $node->removeChild($signature); } - $calculatedDigest = self::makeDigest($node, $algorithm, $canonical); + $calculatedDigest = static::makeDigest($node, $algorithm, $canonical); $informedDigest = $signature->getElementsByTagName('DigestValue')->item(0)->nodeValue; if ($calculatedDigest != $informedDigest) { throw SignerException::digestComparisonFailed(); @@ -320,10 +320,10 @@ public static function digestCheck($xml, $tagname = '', $canonical = self::CANON * @param array $canonical * @return string */ - private static function makeDigest(DOMNode $node, $algorithm, $canonical = self::CANONICAL) + protected static function makeDigest(DOMNode $node, $algorithm, $canonical = self::CANONICAL) { //calcular o hash dos dados - $c14n = self::canonize($node, $canonical); + $c14n = static::canonize($node, $canonical); $hashValue = hash($algorithm, $c14n, true); return base64_encode($hashValue); } @@ -334,7 +334,7 @@ private static function makeDigest(DOMNode $node, $algorithm, $canonical = self: * @param array $canonical * @return string */ - private static function canonize(DOMNode $node, $canonical = self::CANONICAL) + protected static function canonize(DOMNode $node, $canonical = self::CANONICAL) { return $node->C14N( $canonical[0], diff --git a/src/SignerMulti.php b/src/SignerMulti.php new file mode 100755 index 0000000..b4ef0e8 --- /dev/null +++ b/src/SignerMulti.php @@ -0,0 +1,37 @@ + + * @link http://github.com/nfephp-org/sped-common for the canonical source repository + */ + +namespace NFePHP\Common; + +class SignerMulti extends Signer +{ + /** + * @param string $content + * @return false + */ + public static function existsSignature($content) + { + return false; + } +} diff --git a/tests/SignerMultiTest.php b/tests/SignerMultiTest.php new file mode 100755 index 0000000..f7a090a --- /dev/null +++ b/tests/SignerMultiTest.php @@ -0,0 +1,22 @@ +Teste Assinar mesmo documento 2x', 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'b'); + $xmlsign2x = SignerMulti::sign($certificate, $xmlsign, 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'a'); + $dom = new \DOMDocument('1.0', 'utf-8'); + $dom->loadXML($xmlsign2x); + $this->assertEquals(2, $dom->getElementsByTagName('Signature')->count()); + } +} From db83ea6e23afb83f58ed34984b780c9e78d8e7fb Mon Sep 17 00:00:00 2001 From: Gerson Felipe Schwinn Date: Mon, 1 Jul 2024 18:43:49 -0300 Subject: [PATCH 2/4] Melhorando testes --- tests/SignerMultiTest.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/SignerMultiTest.php b/tests/SignerMultiTest.php index f7a090a..e2c3307 100755 --- a/tests/SignerMultiTest.php +++ b/tests/SignerMultiTest.php @@ -13,10 +13,19 @@ public function testSign(): void $pfx = file_get_contents(__DIR__ . '/fixtures/certs/certificado_teste.pfx'); $certificate = Certificate::readPfx($pfx, 'associacao'); - $xmlsign = SignerMulti::sign($certificate, 'Teste Assinar mesmo documento 2x', 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'b'); - $xmlsign2x = SignerMulti::sign($certificate, $xmlsign, 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'a'); + $xml = ''; + $xml .= ''; + $xml .= 'Teste Assinar mesmo documento 2x'; + $xml .= ''; + $xml .= ''; + + $xmlSignTagB = SignerMulti::sign($certificate, $xml, 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'b'); + $xmlsignTagA = SignerMulti::sign($certificate, $xmlSignTagB, 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'a'); + $dom = new \DOMDocument('1.0', 'utf-8'); - $dom->loadXML($xmlsign2x); + $dom->loadXML($xmlsignTagA); $this->assertEquals(2, $dom->getElementsByTagName('Signature')->count()); + $this->assertEquals('Signature', $dom->getElementsByTagName('a')->item(0)->childNodes->item(1)->nodeName); + $this->assertEquals('Signature', $dom->getElementsByTagName('b')->item(0)->childNodes->item(1)->nodeName); } } From db5f4523f2cd701cfb8ba5e148ba3d141aeee462 Mon Sep 17 00:00:00 2001 From: Gerson Felipe Schwinn Date: Mon, 1 Jul 2024 18:46:37 -0300 Subject: [PATCH 3/4] =?UTF-8?q?Alterando=20coment=C3=A1rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SignerMulti.php | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/SignerMulti.php b/src/SignerMulti.php index b4ef0e8..ea13fb7 100755 --- a/src/SignerMulti.php +++ b/src/SignerMulti.php @@ -1,25 +1,7 @@ - * @link http://github.com/nfephp-org/sped-common for the canonical source repository + * Class to sign multiple times the same xml */ namespace NFePHP\Common; From b3f5418d66ed167e3ce0a53496cae48ad86b0a28 Mon Sep 17 00:00:00 2001 From: Gerson Felipe Schwinn Date: Mon, 1 Jul 2024 18:49:33 -0300 Subject: [PATCH 4/4] Corrigindo tag a ser assinada --- tests/SignerMultiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SignerMultiTest.php b/tests/SignerMultiTest.php index e2c3307..919d120 100755 --- a/tests/SignerMultiTest.php +++ b/tests/SignerMultiTest.php @@ -20,7 +20,7 @@ public function testSign(): void $xml .= ''; $xmlSignTagB = SignerMulti::sign($certificate, $xml, 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'b'); - $xmlsignTagA = SignerMulti::sign($certificate, $xmlSignTagB, 'b', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'a'); + $xmlsignTagA = SignerMulti::sign($certificate, $xmlSignTagB, 'a', 'Id', OPENSSL_ALGO_SHA1, SignerMulti::CANONICAL, 'a'); $dom = new \DOMDocument('1.0', 'utf-8'); $dom->loadXML($xmlsignTagA);