robrichards / xmlseclibs

A PHP library for XML Security
BSD 3-Clause "New" or "Revised" License
387 stars 181 forks source link

Reference URI needed and two X509Certificate tags #193

Closed langaro closed 5 years ago

langaro commented 5 years ago

Hello, thanks for the library. I have two issues taking my sleep.

The first one is I can't get the Reference URI to be in the signature element. The second one is that I have two X509Certificate tags inside X509Data.

image

I'm using a .pfx certificate converted with openSSL (I used this tutorial) to a .pem and a .crt.

The webservice I'm supposed to send this XML is returning an error telling me that the signature do not match with the XML information. I don't know but, according the webservices's documentation I must sign a specific node, not the whole XML, and I'm not specifying this in my code, maybe... is there a way to use a specific xml node to generate the signature?

Finally, here's my code:

` function signXML() {

$doc = new DOMDocument();
$doc->load('signable XML path');

$objDSig = new XMLSecurityDSig('');

$objDSig->setCanonicalMethod(XMLSecurityDSig::C14N);

$objDSig->addReference(
    $doc, 
    XMLSecurityDSig::SHA1, 
    ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'],
    array('force_uri'=>true)
);

$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));

$objKey->passphrase = 'password';

$objKey->loadKey('.pem path', TRUE);

$objDSig->sign($objKey);

$objDSig->add509Cert(file_get_contents('.crt path'));

$objDSig->appendSignature($doc->getElementsByTagName('tcDeclaracaoPrestacaoServico')->item(0));
//I had to specify the tag to append the signature

$doc->save('signed xml path to save');

} `

If someone could help my in this, I would gladly pay a coffee 👍

Thanks in advance

langaro commented 5 years ago

Hey, I was able to put the Reference URI where I want, here's my new code:

`function signXML() {

$doc = new DOMDocument();
$doc->load('signable XML path');

$objDSig = new XMLSecurityDSig('');

$objDSig->setCanonicalMethod(XMLSecurityDSig::C14N);

$objDSig->addReference(
    $doc->getElementsByTagName('InfDeclaracaoPrestacaoServico')->item(0), 
    XMLSecurityDSig::SHA1, 
    ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'],
    array('force_uri'=>true, 'overwrite'=>false)
);
//I'm passing a element getted by tag name because the documentation says I need to sign this specific element

$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));

$objKey->passphrase = 'password';

$objKey->loadKey('.pem path', TRUE);

$objDSig->sign($objKey);

$objDSig->add509Cert(file_get_contents('.crt path'));

$objDSig->appendSignature($doc->getElementsByTagName('tcDeclaracaoPrestacaoServico')->item(0));
//I had to specify the tag to append the signature

$doc->save('signed xml path to save');

}`

I'm not able yet to determine why I'm getting two X509Certificate tags and why the server is returning a non match.

Thanks in advance

langaro commented 5 years ago

Folks, I managed to sign it correctly yet I still need to sign only a specific part of my xml. Has anyone ever done this? Sign a specific node in a XML ignoring the rest?

@robrichards if you want to close this issue I can can open another, thanks.

Thanks in advance