There seems to be a problem with extra whitespace depending of the
original layout of a XML file. Consider the following example.
XML input file A:
<?xml version="1.0"?>
<RootNode><Secret>blub<get$test</Secret></RootNode>
XML input file B:
<?xml version="1.0"?>
<RootNode>
<Secret>blub<get$test</Secret>
</RootNode>
Both files have the same meaning in XML language but if the content of
node "Secret" gets encrypted they are differently saved. The example
application out-file.c (see attachment) generates the following
encrypted XML files:
XML encrypted output of file A:
<?xml version="1.0" encoding="UTF-8"?>
<RootNode>
<Secret>
<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#"
Type="http://www.w3.org/2001/04/xmlenc#Content">
<EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
<CipherData>
<CipherValue>PgcLxYie+I99jvqj6OtmzO/lPX0P/Fb/4mdMaw7DJRM=</CipherValue>
</CipherData>
</EncryptedData>
</Secret>
</RootNode>
XML encrypted output of file B:
<?xml version="1.0" encoding="UTF-8"?>
<RootNode>
<Secret><EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#"
Type="http://www.w3.org/2001/04/xmlenc#Content">
<EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
<CipherData>
<CipherValue>hmUZxuFh9aCS7IdZIO/JXR5r8gPcha8Og08MTM3J9s8=</CipherValue>
</CipherData>
</EncryptedData></Secret>
</RootNode>
As you can already see the CipherValue differs. If you now decrypt both
files a different content of node "Secret" will be generated (try the
application in.c from attachment). The document dump is the same for
both files but if you use xmlNodeGetContent() different values will be
extracted:
xmlNodeGetContent() of encrypted file A:
XXX
blub<get$test
XXX
xmlNodeGetContent() of encrypted file B:
XXXblub<get$testXXX
I added the XXX's to demonstrate the whitespace.
I think the problem has to be in the encryption functions of XMLsec
because several other tests showed that the decryption functions worked
fine.
Any idea what the problem could be?
-Stefan
PS: I'm using xmlsec1-1.2.11 with libxml2-2.6.31 on a Fedora 8 PPC
machine
PSS: The following command is generated by the Makefile (defines could
be interesting?!):
gcc -g -D__XMLSEC_FUNCTION__=__FUNCTION__ -DXMLSEC_NO_GOST=1
-DXMLSEC_NO_XKMS=1 -I/usr/local/xmlsec/include/xmlsec1
-I/usr/include/libxml2 -DXMLSEC_CRYPTO_DYNAMIC_LOADING=1
-DXMLSEC_CRYPTO=\"openssl\" -DUNIX_SOCKETS -g -L/usr/local/xmlsec/lib
-L/usr/lib -ldl -lxmlsec1 -lxslt -lxml2 -lz -lm in.c -o in
#include <libxml/parser.h>
#include <libxml/tree.h>
#ifndef XMLSEC_NO_XSLT
#include <libxslt/xslt.h>
#endif /* XMLSEC_NO_XSLT */
#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
#include <xmlsec/xmlenc.h>
#include <xmlsec/templates.h>
#include <xmlsec/crypto.h>
int main(int argc, char **argv) {
xmlDocPtr doc = NULL;
xmlNodePtr root_node = NULL;
xmlSecKeysMngrPtr mngr = NULL;
xmlSecKeyPtr key = NULL;
if (argc != 2) {
fprintf (stderr, "ERROR: You have to specify an input file.\n");
exit (EXIT_FAILURE);
}
/* Init libxml and libxslt libraries */
xmlInitParser ();
LIBXML_TEST_VERSION
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
xmlSubstituteEntitiesDefault (1);
#ifndef XMLSEC_NO_XSLT
xmlIndentTreeOutput = 1;
#endif /* XMLSEC_NO_XSLT */
/* Init xmlsec library */
if (xmlSecInit () < 0) {
fprintf (stderr, "Error: xmlsec initialization failed.\n");
exit (EXIT_FAILURE);
}
/* Load default crypto engine if we are supporting dynamic
* loading for xmlsec-crypto libraries. Use the crypto library
* name ("openssl", "nss", etc.) to load corresponding
* xmlsec-crypto library.
*/
if (xmlSecCryptoDLLoadLibrary (BAD_CAST XMLSEC_CRYPTO) < 0) {
fprintf (stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
"that you have it installed and check shared libraries path\n"
"(LD_LIBRARY_PATH) envornment variable.\n");
exit (EXIT_FAILURE);
}
/* Init crypto library */
if (xmlSecCryptoAppInit (NULL) < 0) {
fprintf (stderr, "Error: crypto initialization failed.\n");
exit (EXIT_FAILURE);
}
/* Init xmlsec-crypto library */
if (xmlSecCryptoInit () < 0) {
fprintf (stderr, "Error: xmlsec-crypto initialization failed.\n");
exit (EXIT_FAILURE);
}
doc = xmlReadFile (argv[1], NULL, 0);
if (doc == NULL) {
fprintf (stderr, "ERROR\n");
exit (EXIT_FAILURE);
}
mngr = xmlSecKeysMngrCreate ();
if (mngr == NULL) {
fprintf (stderr, "Error: failed to create keys manager.\n");
exit (EXIT_FAILURE);
}
if (xmlSecCryptoAppDefaultKeysMngrInit (mngr) < 0) {
fprintf (stderr, "Error: failed to initialize keys manager.\n");
exit (EXIT_FAILURE);
}
key = xmlSecKeyReadMemory (xmlSecKeyDataDesId, "012345670123456701234567", 24);
if (key == NULL) {
fprintf (stderr,"Error: failed to load password\n");
exit (EXIT_FAILURE);
}
/* add key to keys manager, from now on keys manager is responsible
* for destroying key
*/
if (xmlSecCryptoAppDefaultKeysMngrAdoptKey (mngr, key) < 0) {
fprintf (stderr,"Error: failed to add key to keys manager\n");
exit (EXIT_FAILURE);
}
key = NULL;
/* create encryption context */
xmlSecEncCtxPtr encCtx = xmlSecEncCtxCreate (mngr);
if (encCtx == NULL) {
fprintf (stderr,"Error: failed to create encryption context\n");
exit (EXIT_FAILURE);
}
xmlNodePtr secret_node = xmlDocGetRootElement(doc);
xmlNodePtr node = xmlSecFindNode (secret_node, xmlSecNodeEncryptedData, xmlSecEncNs);
if (node != NULL) { /* an encrypted data node was found */
if (xmlSecEncCtxDecrypt(encCtx, node) < 0 || (encCtx->result == NULL)) {
fprintf (stderr, "Error: decryption failed\n");
exit (EXIT_FAILURE);
}
if (encCtx->resultReplaced != 1) {
fprintf (stderr, "Error: The result should be replaced. WTH wasn't it?\n");
exit (EXIT_FAILURE);
}
}
printf ("*****************************************\n");
xmlDocDump(stdout, doc);
printf ("*****************************************\n");
for (node = xmlDocGetRootElement(doc)->children; node != NULL; node = node->next) {
if (xmlStrEqual (node->name, "Secret")) {
printf ("Content: XXX%sXXX\n", xmlNodeGetContent (node));
}
}
return 0;
}
#
#
#
PROGRAMS = in out-file
CC = gcc
CFLAGS += -g $(shell /usr/local/xmlsec/bin/xmlsec1-config --cflags) -DUNIX_SOCKETS
LDFLAGS += -g $(shell /usr/local/xmlsec/bin/xmlsec1-config --libs)
all: $(PROGRAMS)
clean:
@rm -rf $(PROGRAMS)
#include <libxml/parser.h>
#include <libxml/tree.h>
#ifndef XMLSEC_NO_XSLT
#include <libxslt/xslt.h>
#endif /* XMLSEC_NO_XSLT */
#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
#include <xmlsec/xmlenc.h>
#include <xmlsec/templates.h>
#include <xmlsec/crypto.h>
int main(int argc, char **argv) {
xmlDocPtr doc = NULL;
xmlNodePtr root_node = NULL;
xmlSecKeysMngrPtr mngr = NULL;
xmlSecKeyPtr key = NULL;
if (argc != 3) {
fprintf (stderr, "ERROR: You have to specifiy an input and an output file.\n");
exit (EXIT_FAILURE);
}
/* Init libxml and libxslt libraries */
xmlInitParser ();
LIBXML_TEST_VERSION
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
xmlSubstituteEntitiesDefault (1);
#ifndef XMLSEC_NO_XSLT
xmlIndentTreeOutput = 1;
#endif /* XMLSEC_NO_XSLT */
/* Init xmlsec library */
if (xmlSecInit () < 0) {
fprintf (stderr, "Error: xmlsec initialization failed.\n");
exit (EXIT_FAILURE);
}
/* Load default crypto engine if we are supporting dynamic
* loading for xmlsec-crypto libraries. Use the crypto library
* name ("openssl", "nss", etc.) to load corresponding
* xmlsec-crypto library.
*/
if (xmlSecCryptoDLLoadLibrary (BAD_CAST XMLSEC_CRYPTO) < 0) {
fprintf (stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
"that you have it installed and check shared libraries path\n"
"(LD_LIBRARY_PATH) envornment variable.\n");
exit (EXIT_FAILURE);
}
/* Init crypto library */
if (xmlSecCryptoAppInit (NULL) < 0) {
fprintf (stderr, "Error: crypto initialization failed.\n");
exit (EXIT_FAILURE);
}
/* Init xmlsec-crypto library */
if (xmlSecCryptoInit () < 0) {
fprintf (stderr, "Error: xmlsec-crypto initialization failed.\n");
exit (EXIT_FAILURE);
}
doc = xmlReadFile (argv[1], NULL, 0);
if (doc == NULL) {
fprintf (stderr, "ERROR\n");
exit (EXIT_FAILURE);
}
xmlNodePtr secret_node = xmlDocGetRootElement (doc)->children;
for (; secret_node != NULL; secret_node = secret_node->next)
if (xmlStrEqual (secret_node->name, "Secret"))
break;
printf ("*****************************************\n");
xmlDocDump(stdout, doc);
printf ("*****************************************\n");
printf ("Content: XXX%sXXX\n", xmlNodeGetContent (secret_node));
xmlNodePtr encDataNode = xmlSecTmplEncDataCreate (doc, xmlSecTransformDes3CbcId, NULL, xmlSecTypeEncContent, NULL, NULL);
if (encDataNode == NULL) {
fprintf (stderr, "Error: failed to create encryption template\n");
exit (EXIT_FAILURE);
}
if (xmlSecTmplEncDataEnsureCipherValue (encDataNode) == NULL) {
fprintf (stderr, "Error: failed to add CipherValue node\n");
exit (EXIT_FAILURE);
}
xmlSecEncCtxPtr encCtx = xmlSecEncCtxCreate (NULL);
if (encCtx == NULL) {
fprintf (stderr, "Error: failed to create encryption context\n");
exit (EXIT_FAILURE);
}
encCtx->encKey = xmlSecKeyReadMemory (xmlSecKeyDataDesId, BAD_CAST "012345670123456701234567", 24);
if (encCtx->encKey == NULL) {
fprintf (stderr,"Error: failed to load password\n");
exit (EXIT_FAILURE);
}
if (xmlSecEncCtxXmlEncrypt (encCtx, encDataNode, secret_node) < 0) {
fprintf (stderr, "Error: encryption failed\n");
exit (EXIT_FAILURE);
}
if (xmlSaveFormatFileEnc (argv[2], doc, "UTF-8", 1) < 0) {
fprintf (stderr, "ERROR\n");
exit (EXIT_FAILURE);
}
return 0;
}
_______________________________________________
xmlsec mailing list
[email protected]
http://www.aleksey.com/mailman/listinfo/xmlsec