- Home
- Download
- News
- Documentation
- FAQ
- XML Digital Signature

- Interop report
- Online Verifier
- Example 1
- Example 2
- Example 3
- Example 4

- XML Encryption

- Interop report

- XML Canonicalization
- Reporting Bugs
- Mailing list

## XML Digital Signature
Example 4. 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