selective-php / xmldsig

Sign XML Documents with Digital Signatures
MIT License
73 stars 34 forks source link

Unable to verify partial (signDocument) #28

Open lsv opened 4 months ago

lsv commented 4 months ago

I added a test

    /**
     * Test.
     *
     * @dataProvider providerTestSignAndVerify
     *
     * @param string $privateKeyFile The key file
     * @param string $publicKeyFile The key file
     * @param string $password The file password
     *
     * @return void
     */
    public function testSignAndVerifyPartial(string $privateKeyFile, string $publicKeyFile, string $password)
    {
        $files = [
            __DIR__ . '/example4.xml',
        ];

        $algos = [
            Algorithm::METHOD_SHA1,
            Algorithm::METHOD_SHA224,
            Algorithm::METHOD_SHA256,
            Algorithm::METHOD_SHA384,
            Algorithm::METHOD_SHA512,
        ];

        foreach ($files as $filename) {
            foreach ($algos as $algo) {
                $privateKeyStore = new PrivateKeyStore();

                if (pathinfo($privateKeyFile, PATHINFO_EXTENSION) === 'p12') {
                    $privateKeyStore->loadFromPkcs12(file_get_contents($privateKeyFile), $password);
                } else {
                    $privateKeyStore->loadFromPem(file_get_contents($privateKeyFile), $password);
                }

                $algorithm = new Algorithm($algo, $algo);
                $cryptoSigner = new CryptoSigner($privateKeyStore, $algorithm);

                $xmlSigner = new XmlSigner($cryptoSigner);
                $xmlSigner->setReferenceUri('');

                $xml = new DOMDocument();
                $xml->preserveWhiteSpace = true;
                $xml->formatOutput = false;
                $xml->loadXML(file_get_contents($filename));
                $xpath = new DOMXPath($xml);
                $elementToSign = $xpath->query('/References/Book/Author')->item(0);

                $signedXml = $xmlSigner->signDocument($xml, $elementToSign);

                // verify
                $publicKeyStore = new PublicKeyStore();
                if (pathinfo($publicKeyFile, PATHINFO_EXTENSION) === 'p12') {
                    $publicKeyStore->loadFromPkcs12(file_get_contents($publicKeyFile), $password);
                } else {
                    $publicKeyStore->loadFromPem(file_get_contents($publicKeyFile));
                }

                $cryptoVerifier = new CryptoVerifier($publicKeyStore);
                $xmlSignatureVerifier = new XmlSignatureVerifier($cryptoVerifier);

                $isValid = $xmlSignatureVerifier->verifyXml($signedXml);

                $this->assertTrue($isValid, 'Could not validate partial signed xml document');
            }
        }
    }

Which tests the partial (signDocument)

This is the xml output of the $signedXml

<?xml version="1.0"?>
<References>
    <Book>
        <Author>
            <FirstName>Bruce</FirstName>
            <LastName>Schneier</LastName>
        </Author>
        <Title>Applied Cryptography</Title>
    </Book>
    <Web>
        <Title>XMLSec</Title>
        <Url>http://www.aleksey.com/xmlsec/</Url>
    </Web>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>JcCwDiYORvy5oZax2ZLPbtOMWeU=</DigestValue></Reference></SignedInfo><SignatureValue>feoBWMSYKSjh2/Vu5L/szUDL/7hpu6cxwy/LTlwP8XwKGzq3WFBYJRNO2s/CdDSCAyH2Gka2xTZslVlxnpcloeg8dVL36Z6OXoPNH/B8LppE+r4cB9ivXu/cCbes0SHnnP+zG4aRV5W9NRyevMWdlg9WdtNXUDtZ0aseWNnOjjI=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>2smhWoycTnVVPvBI8Dt9Utl6jZmMcWx34lCTt8Noeezj1JCgHCnuRr7fYSWz029wuG5T0nDpHtkXsSp10u6QF128RZYFJWdECtCtqXZeefTkpq7R95jz/QSb7wzJcZHDY/fxHg/shnfBjf8k+j0w4fBv+JbMzly/rciiJAuGLP8=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue></KeyInfo></Signature></References>

Is this normal, or?

odan commented 4 months ago

Have you tried this example?

https://github.com/selective-php/xmldsig?tab=readme-ov-file#signing-only-specific-part-of-an-xml-document

lsv commented 4 months ago

Yes, thats actually what the test is doing.