|
XML Digital Signature
Example 3. Verifying signatures in the document.
In this example we will verify a signature created in the
previous
example. The source code for this example is included into the package:
source code
and the signed document.
Step 0. Initializing LibXML, OpenSSL and XML Security Library.
Creating DSig context.
Before using the libraries we need to initialize them. This
should be done once in the beginning of your program.
int rnd_seed = 0;
xmlSecKeysMngrPtr keysMngr = NULL;
xmlSecDSigCtxPtr dsigCtx = NULL;
/**
* Init OpenSSL
*/
while (RAND_status() != 1) {
RAND_seed(&rnd_seed, sizeof(rnd_seed));
}
/*
* Init libxml
*/
xmlInitParser();
LIBXML_TEST_VERSION
/*
* Init xmlsec
*/
xmlSecInit();
/**
* Create Keys managers
*/
keysMngr = xmlSecSimpleKeysMngrCreate();
if(keysMngr == NULL) {
fprintf(stderr, "Error: failed to create
keys manager\n");
goto done;
}
dsigCtx = xmlSecDSigCtxCreate(keysMngr);
if(dsigCtx == NULL) {
fprintf(stderr,"Error: failed to create
dsig context\n");
goto done;
}
Step 1. Loading the document.
XMLDSig requires the XML document to be loaded with all default
attributes propagated to the nodes, all entities replaced, etc. (this
is required for correct document
Canonicalization
). In the LibXML this means that you need to take special actions
when loading document from an URI:
xmlDocPtr doc = NULL;
/**
* build an XML tree from a the file;
we need to add default
* attributes and resolve all character
and entities references
*/
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS
| XML_COMPLETE_ATTRS;
xmlSubstituteEntitiesDefault(1);
/**
* Load doc
*/
doc = xmlParseFile(argv[2]);
if (doc == NULL) {
fprintf(stderr, "Error
: unable to parse file \"%s\"\n", argv[1]);
goto done;
}
/**
* Check the document is of the right
kind
*/
if(xmlDocGetRootElement(doc) == NULL) {
fprintf(stderr,"Error:
empty document for file \"%s\"\n", argv[1]);
goto done;
}
In this example we set global flags to control how the document
is loaded. In the real life you would probably want to control the
loading on "per-document" basis. Check the libxml/c14n.h header file
from LibXML distribution for details.
Step 2. Verify It!
We are ready to sign the document but first we need to find
<Signature> node:
xmlNodePtr signNode;
xmlSecDSigResultPtr result = NULL;
signNode = xmlSecFindNode(xmlDocGetRootElement(doc),
BAD_CAST "Signature", xmlSecDSigNs);
if(signNode == NULL) {
fprintf(stderr,"Error: failed
to find Signature node\n");
goto done;
}
/**
* Verify It!
*/
ret = xmlSecDSigValidate(dsigCtx, NULL, NULL, signNode, &result);
if(ret < 0) {
fprintf(stderr,"Error: verification
failed\n");
goto done;
}
Step 3. Print results.
In our example we will use an XML Security Library function to print the
verification results. Real application should process signature objects list
(there could be more than one signature in the document!) by itself.
/*
* Print out result
*/
xmlSecDSigResultDebugDump(result, stdout);
Step 4. Cleanup.
At the end we need to destroy DSig context, the doc and KeysManager;
shutdown libxml and OpenSSL
(please note that we do not delete creted Signature and Reference
nodes separatelly because both nodes are included into the XML document
doc):
/**
* Cleanup
*/
if(result != NULL) {
xmlSecDSigResultDestroy(result);
}
if(dsigCtx != NULL) {
xmlSecDSigCtxDestroy(dsigCtx);
}
if(doc != NULL) {
xmlFreeDoc(doc);
}
if(keysMngr != NULL) {
xmlSecSimpleKeysMngrDestroy(keysMngr);
}
xmlSecShutdown();
/*
* Shutdown libxml
*/
xmlCleanupParser();
/*
* Shutdown OpenSSL
*/
RAND_cleanup();
ERR_clear_error();
Appendix A. The verification output.
= SIGNATURE (validate)
== result: OK
== sign method: http://www.w3.org/2000/09/xmldsig#dsa-sha1
== key name: (null)
== key origin: 0
== start buffer:
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"></SignatureMethod>
<Reference Id="reference-1" URI="#xpointer(id('SomeData'))">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"></Transform>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>x/tL8hKZQyExW6ba0pi5h8eWRCc=</DigestValue>
</Reference>
</SignedInfo>
== end buffer
== SIGNED INFO REFERENCES
==== REFERENCE
===== ref type: SignedInfo Reference
===== result: OK
===== digest method: http://www.w3.org/2000/09/xmldsig#sha1
===== uri: #xpointer(id('SomeData'))
===== type: NULL
===== id: reference-1
===== start buffer:
<Info Id="SomeData">
<!-- Commentary -->
<Data1> Some data </Data1>
<Data2> More data </Data2>
</Info>
===== end buffer
Appendix B. The signed document.
<?xml version="1.0" encoding="UTF-8"?>
<Letter>
Hello, World!
<Info Id="SomeData">
<!-- Commentary -->
<Data1> Some data </Data1>
<Data2> More data </Data2>
</Info>
<Something>Some important data</Something><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#dsa-sha1"/>
<Reference Id="reference-1" URI="#xpointer(id('SomeData'))">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>x/tL8hKZQyExW6ba0pi5h8eWRCc=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>uwYbk29Juoe8B0eCW6aAjw4t+QBT7oQsjAmQnu8fFQPNy0RwP6pWNA==</SignatureValue>
<KeyInfo Id="">
<KeyValue>
<DSAKeyValue>
<P>
imW6KYBPYXAf6itSAuYs1aLPfs8/vBEiusv/pl1XMiuMvB7vyiJgSj8/NTkRci/U
X/rVXv8rbCRjvYFX3x5/53f4hc6HKz7JQI4qqB7Fl5N86zp+BsQxNQ4tzous9S2H
Td2/zdTwVsvO+H9l3FahmVp/m2IHE4W27JYoF49qP10=
</P>
<Q>
v/xzWqjRviekk2rMW3wpYspT9Us=
</Q>
<G>
UIyzUDlLe6uCCgF4Rh98fiKZvg64UJ4FM5L+WbCSMmVsFN06fTwxy3naPPOCzzou
fsHv/Bve2gvrDvd078oXWJJf9A44pIZnJkdjEhm2RsDFpXNq0tPKZFcjVsdmqg4M
X6YNuwpvZuTwSoDG5u1QMN0mmH9gmbIT3j9x4MO+7EY=
</G>
<Y>
On+KBJE3q1TRhG9RspNX01VI5C0VzSy4N/QyC4YzEENoq3GJkKHIYq+grq9ZqV9x
g2Geo/3mqhdcENOtYRmWEfOZJj18oukD6TNceYRZ4HjHjK3WY3wK2OV6QOly+k3f
xgEQpP/7IlCka5YICLuHXrbqjn5b0XcK9L2GDtWOyjs=
</Y>
</DSAKeyValue>
</KeyValue>
</KeyInfo>
</Signature></Letter>
Aleksey Sanin
|