XMLDSIG Enveloping Signatures

2,088 views
Skip to first unread message

Lars

unread,
Jan 6, 2013, 9:13:21 AM1/6/13
to xmlse...@googlegroups.com

Hi,

I found this library seaching the internet, and finally I found something promissing for what I have been seaching for.
I have been struggling for a couple of days trying to figure out how to use xmlseclibs to sign XML files by the use of XMLDSIG.
Based on the library and the examples in the tests section, I can easily get it to work in terms of the enveloped kind of signatures.
But what I need is the ENVELOPING kind of signature, with an object element of the signature itself, identified via the Reference URI.
Further, I will have to use a X509 certificate to sign the XML file (have also got that to work, based on the examples in the tests section).
I have tried to use the addObject method in various ways, but I simply can't figure out how to get things to work.

Anybody out there, who could please help me with some examples / hints of how to use xmlseclibs for ENVELOPING signatures ?

Regards,

Lars

Rob Richards

unread,
Jan 11, 2013, 7:35:22 AM1/11/13
to xmlse...@googlegroups.com, Lars
Do you have an example of the code you are using? I will also try to add
an example of the addObject method as a unit test when I get a chance.

Rob

Lars

unread,
Jan 13, 2013, 4:18:06 AM1/13/13
to xmlse...@googlegroups.com
Hi Rob,

Thanks for your reply. Here is what I have so far.

The PHP-code for a simple example:

<?php

require(dirname(__FILE__) . '/xmlseclibs.php');


if (file_exists(dirname(__FILE__) . '/sign-basic-test.xml')) {

    unlink(dirname(__FILE__) . '/sign-basic-test.xml');

}

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;

$tobesigned = $dom->createElement('ToBeSigned');
$value = $dom->createElement('Value', 'Hello World');

$dom->appendChild($tobesigned);
$tobesigned->appendChild($value);

$objDSig = new XMLSecurityDSig();

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

$node = $objDSig->addObject($dom->documentElement);

$objDSig->addReference($node, XMLSecurityDSig::SHA1, NULL, array('force_uri' => true));

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

/* load private key */

$objKey->loadKey(dirname(__FILE__) . '/privkey.pem', TRUE);

/* if key has Passphrase, set it using $objKey->passphrase = <passphrase> " */

$objDSig->sign($objKey);

/* Add associated public key */

$objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/mycert.pem'));

$objDSig->appendSignature($dom->documentElement);

$dom->save(dirname(__FILE__) . '/sign-basic-test.xml');

echo "DONE";

?>

and the generated XML file:

(I have cut down the SignatureValue and the x509 Certificate, to make it easier to read)


<?xml version="1.0" encoding="UTF-8"?>
<ToBeSigned>
  <Value>Hello World</Value>
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    <ds:Reference URI="#pfx394571ed-522b-425e-be9a-2b47c8bce5e2">
     <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms>
     <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
     <ds:DigestValue>Ao8wIiNH7AoEbyvddx1Dapy6CY4=</ds:DigestValue>
    </ds:Reference>
   </ds:SignedInfo>
   <ds:SignatureValue> .... ZL30WTxTH09679o3/OUF8dodsRqa46++Dqm .... </ds:SignatureValue>
   <ds:KeyInfo>
   <ds:X509Data>
    <ds:X509Certificate> .... MIIEVDCCAzygAwIBAgIJAPTrkMJbCOr1MA0G .... </ds:X509Certificate>
   </ds:X509Data>
   </ds:KeyInfo>
   <ds:Object Id="pfx394571ed-522b-425e-be9a-2b47c8bce5e2">
    <ToBeSigned>
     <Value>Hello World</Value>
    </ToBeSigned>
   </ds:Object>
  </ds:Signature>
</ToBeSigned>

The final challenge is to have the XML file generated without line no 2, 3 and 26 (the last one), so you end up with a correct ENVELOPING signature, with the <ds:Signature> as the starting and ending element.

Regards,

Lars

Rob Richards

unread,
Jan 13, 2013, 9:35:30 PM1/13/13
to xmlse...@googlegroups.com, Lars
Ah, very simple here. When you pass the element to the addObject method,
it is actually importing the element into its own document. So there is
no need to append the signature at the end of your code and the output
needs to be done from the signature class. In your origonal code, when
you had the signature appending to the document element, it was actually
importing the signature block into the the originating document. This is
why when you look at the code I sent here you can use the $node value to
get the owning document to output rather than the $dom document you
started with - you ended up creating a new document containing the
enveloping signature.

i.e. change:
$objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/mycert.pem'));
$objDSig->appendSignature($dom->documentElement);
$dom->save(dirname(__FILE__) . '/sign-basic-test.xml');

to:

$objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/mycert.pem'));
echo $node->ownerDocument->save(dirname(__FILE__) . '/sign-basic-test.xml');

Let me know if any questions.

Rob

Lars

unread,
Jan 16, 2013, 5:07:45 AM1/16/13
to xmlse...@googlegroups.com
Hi Rob,

Thanks for your help.

It works fine. Just one more small thing. Can't figure out how to ensure, that the final XML file gets encoded with UTF-8, so the first line in the final XML file would be : <?XML version="1.0" encoding="UTF-8"?>

Regards,

Lars


Den søndag den 6. januar 2013 15.13.21 UTC+1 skrev Lars:

Rob Richards

unread,
Jan 16, 2013, 7:07:14 AM1/16/13
to xmlse...@googlegroups.com, Lars
Just a note that the encoding isn't required in your case since UTF-8 is the default encoding when not specified in the prolog. If you really need to add for some reason though, just set the DOMDocument encoding property. i.e.:


$objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/mycert.pem'));
$node->ownerDocument->encoding = "UTF-8";

echo $node->ownerDocument->save(dirname(__FILE__) . '/sign-basic-test.xml');

Rob

Lars

unread,
Feb 22, 2013, 4:58:17 AM2/22/13
to xmlse...@googlegroups.com, Lars
Hi Rob,
 
Sorry to bother you again, but no matter what I try, I can't get the <SignatureValue> right, when I am trying to make the Enveloping signature. I have a signed XML reference file, so I know what the <DigestValue> and the <SignatureValue> are supposed to be.
 
I beleive it's the <Transforms> part there is causing the problems (there is no Transforms in my reference file). I have tried in varius ways to exclude the <Transforms> part without any sucess so far.
 
Could you please give me som hints of how to exclude the <Transforms> part ?
 
Thanks in advance
 
Lars

Rob Richards

unread,
Mar 30, 2013, 4:58:28 AM3/30/13
to xmlse...@googlegroups.com, Lars
The library defaults to adding a transforms node even if it ends up being empty. i.e. if no transforms it will set at least the default canonicalization if specified; otherwise will have an empty transform node. Although the signatures end up being different, does the document validate by the end consumer?

Rob

syed mohideen

unread,
Sep 3, 2014, 8:50:26 AM9/3/14
to xmlse...@googlegroups.com
Hi ,

What is the computation of Digest Value? eg., Ao8wIiNH7AoEbyvddx1Dapy6CY4=
Does it computation of Certificate + XML Content or XML Content only?.




Rgds.
Syed

Juan Carlos

unread,
Sep 3, 2014, 11:00:35 AM9/3/14
to xmlse...@googlegroups.com
It is only XML content

The digest value you can calculate as this:

    $canonicalized = $objDSig->documentElement->C14N(false,false);
    $digest = base64_encode(pack("H*", sha1($canonicalized)));
             
    echo '<h2>Your Digest calculated ...</h2><pre>' . htmlspecialchars($digest, ENT_QUOTES) . '</pre>';

Regards, Juan.

Juan Carlos

unread,
Sep 3, 2014, 11:03:03 AM9/3/14
to xmlse...@googlegroups.com
Sorry in your case change the following 

$canonicalized = $objDSig->documentElement->C14N(false,false);

it would be ....

$canonicalized = $dom->documentElement->C14N(false,false);

Regards, Juan.

syed mohideen

unread,
Sep 12, 2014, 11:55:04 AM9/12/14
to xmlse...@googlegroups.com

Sorry Juan,

Could you able to interpret in c# for this?.
Reply all
Reply to author
Forward
0 new messages