7

I've been tossed into the world of XML digital signatures with an iOS project I'm working on; I need to verify the digital signature of a SAML assertion.

I've been reading a lot about validating XML signatures, and I think I get the basics about how it signs the digest with the private key and I can verify it with the public key (which should be in the included x509 certificate) so I can be certain of the SAML token's source.

I found a C libray, xmlsec, that looks like it has a lot of the code I need for verifying the signature and have been working on trying to implement that. However, I haven't been able to figure it out. From what I understand, I'm pretty sure I would have to compile the library in with my code. I've copied the source into my project, but I get errors during compile about things not being defined.

Before I spend countless hours heading down that path, I figured I would reach out to the community and see if anyone has had any experience verifying an xml digital signature and whether they could give insight on implementing that in an iOS project.

For what it's worth, here's a chunk of the SAML assertion I'm getting from the single sign-on service:

<?xml version="1.0" encoding="UTF-16"?>
<saml:Assertion ID="oQ2YZuHBspA_f91HM8o3.o6ZZla" IssueInstant="2011-05-06T00:51:40.733Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<saml:Issuer>[...]</saml:Issuer>
<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="#oQ2YZuHBspA_f91HM8o3.o6ZZla">
            <ds:Transforms>
                <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                <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>zj4pCHBNMln+28Jq/v1YIScfiuw=</ds:DigestValue>
        </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>[...]</ds:SignatureValue>
    <ds:KeyInfo>
        <ds:X509Data>
            <ds:X509Certificate>MIIDVjCCAj6gAwIBAgIGAS67wkWCMA0GCSqGSIb3[...]7bgf</ds:X509Certificate>
        </ds:X509Data>
        <ds:KeyValue>
            <ds:RSAKeyValue>
                <ds:Modulus>[...]</ds:Modulus>
                <ds:Exponent>AQAB</ds:Exponent>
            </ds:RSAKeyValue>
        </ds:KeyValue>
    </ds:KeyInfo>
</ds:Signature>
Perception
  • 79,279
  • 19
  • 185
  • 195
Daniel
  • 872
  • 1
  • 11
  • 20
  • no experience in verifying... but what compiler errors are you getting when trying to include xmlsec? Are you linking against libxml? – shawnwall May 27 '11 at 01:01
  • The errors are mostly with getting the header files included; the header/source files use include statements with angle brackets, so its not looking for the source in the project, but in the header search paths...then once I get those included, there are errors with the preprocessor definitions and some compiling settings. I am linking against libxml, its simply getting xmlsec included that's proven so difficult. Can't find anyone who's done it successfully with an iOS project. – Daniel May 27 '11 at 17:51

1 Answers1

9

Compiling xmlsec for iPhone is a bit tricky but can be done.

First of all, some general considerations:

  1. xmlsec is a GNU project using the GNU build system; building one such project amounts to running a script (configure) and then executing make. configure will create a Makefile tailored for your exact system configuration and will allow you to choose which options of xmlsec to include or not in you build;

  2. xmlsec has several dependencies from other libraries: libssl, libcrypto (part of openssl), libxslt, libxml2, libz, and libiconv. Only libxml2 and libz are available in the iPhone SDK and you will need to have all of the others available on your system and already compiled. Those libraries are all GNU projects that you can compile by applying the same approach as the one I describe later for xmlsec. One note: libxslt. Apple includes libxslt in the iPhone SDK, but does not make the .h available, so you are not allowed to link to libxslt.dylib which comes with the iPhone SDK and you will have to compile it on your own.

  3. importing the source files from xmlsec into an iPhone project is difficult unless you know which files are proper to xmlsec and which are simple dependencies (xmlsec source tree includes openssl, gnutls, etc that are not certainly necessary to be there), but above all because you cannot control which optional features of xmlsec you would like to include (or exclude) in your build, like configure does for you;

  4. the approach I preferred is, therefore, properly using configure so as to produce an iPhone-specific Makefile, and then build a static library (since you are not allowed to use external dylib on iPhone);

The steps, concretely, to compile xmlsec for iPhone are:

0 - install and compile all the dependencies; if you cannot find them already ported for iPhone, you can apply (recursively) this same approach to them;

1 - cd to libxmlsec root and execute the command:

CFLAGS=" -arch armv6 -std=c99 -isysroot /Volumes/ext/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk" CC="/Volumes/ext/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2" ./configure --host=arm-apple-darwin10 --disable-shared --disable-crypto-dl --with-libxml=<path_to_where_libxml_is> --with-libxslt=<path_to_where_libxslt_is> --with-openssl=<path_to_where_openssl_is>

in the command above, I am assuming that libxml headers and executables will be found by the compiler since they are part of the SDK. Otherwise include them also.

2 - configure will produce a lot of output and, if everything goes right, you will be able to execute the command:

make

3 - this should run finely to completion and produce your output file: src/.libs/libxmlsec1.a that you can link in your iPhone project (together with all the rest of depended upon libraries).

Finally, a tutorial about compiling openSSL for iPhone.

NSGod
  • 22,699
  • 3
  • 58
  • 66
sergio
  • 68,819
  • 11
  • 102
  • 123
  • thanks for the great solution. sorry i missed awarding the bounty. – Chad Udell May 30 '11 at 19:49
  • Thanks so much for this detailed solution--but I'm afraid you may need to bear with me further as we're deeper into the compiler than I'm familiar with. Ultimately, I want a fat static library for the simulator and the device; currently I'm just working on the simulator. I've successfully built the libraries for openssl and libxslt. However, when I try to `make` xmlsec, I get a warning that libcrypto.a is not portable and shortly after that this error: `.libs/libxmlsec1-openssl.a(libcrypto.a) is not an object file (not allowed in a library with multiple architectures)`. – Daniel May 31 '11 at 17:40
  • no problem... you can use, e.g., the compile option `-arch="arm6 arm7 i386"` and this would do it for you. i am saying it out of my mind, so if it does not work, tell and I'll check it somewhere... or you could build "single platform" libraries and then use lipo to make them fat. – sergio May 31 '11 at 17:50
  • I started by building single platform libraries and was planning on using lipo to make them fat. I think I have built the libraries for the simulator correctly (i386) but now that I am trying to build xmlsec, I get the error about libcrypto.a not being an object file. – Daniel May 31 '11 at 18:05
  • to build for i386, you should not need anything special. just execute `./configure --disable-shared --disable-crypto-dl` and then `make`. it has worked for me. – sergio May 31 '11 at 18:16
  • one more thing: I realize the only approach that makes sense is the lipo one. specifying multiple platforms in -arch will not work. – sergio May 31 '11 at 18:16
  • Okay, I realized what I was doing wrong previously (I had copied and pasted from your answer and had forgotten to change the architecture to i386 for the simulator). I've gotten that all straightened out and confirmed that openssl and libxslt are compiled for i386, but now I'm getting this error: `ld: warning: ignoring file ../src/openssl/.libs/libxmlsec1-openssl.a, file was built for archive which is not the architecture being linked (i386)`. Here's where my lack in understanding of the compiler comes in--this file has been created as part of this make process...why wouldn't it be i386 too? – Daniel May 31 '11 at 19:01
  • The actual errors come after that warning, btw. Errors about undefined symbols (undoubtedly related to the fact that it's ignoring libxmlsec1-oppenssl.a). – Daniel May 31 '11 at 19:02
  • I am pretty sure that you `.a` static library has been built, since it does not need linking. anyway, cure is: `make distclean; configure.... ; make` – sergio May 31 '11 at 19:28
  • I'm not able to get past errors about undefined symbols. Here's the summary of what's happening: http://pastebin.com/STmBRMsP At the top I show what I'm doing for configure, and then I run make. After a few seconds, I get errors about undefined symbols. Parts I didn't think were helpful I replaced with [...]. I don't understand why libxmlsec1-openssl.la would be a shared library if shared is disabled. I really appreciate your help, Sergio. – Daniel Jun 01 '11 at 13:45
  • It seems that the failing command tries to build an executable, `xmlsec1`, which somehow link in the shared library. Thus, one possibility is removing the `--disable-shared` flag, so that dynamic libraries are built and `xmlsec1` is built successfully and overall compilation goes further on. Otherwise, I have found 2 configure flags that might help: `--enable-apps-crypto-dl=no` and `--enable-static-linking`. You might give a try to this. First, enable shared libraries (in the end you would only use the static ones, of course), which seems easier. – sergio Jun 01 '11 at 16:06
  • Hi, have you got any improvements? – sergio Jun 01 '11 at 19:03
  • I just tried removing --disable-shared and got a similar error; undefined symbols after a warning: `ignoring file ../src/.libs/libxmlsec1.dylib, file was built for unsupported file format which is not the architecture being linked (i386)`. I noticed that without the --disable-shared, it was trying to build for x86_64. – Daniel Jun 01 '11 at 20:01
  • interesting... anyway, I compiled for i386 and I had the same error with xmlsec1... the fact is that the library was actually creates (and it makes sense!) `ls -l ./src/.libs/libxmlsec1.a // -rw-r--r-- 1 sergio wheel 727176 Jun 1 22:23 ./src/.libs/libxmlsec1.a` – sergio Jun 01 '11 at 20:25
  • I used this configure line: `CFLAGS=" -arch i386 -std=c99" CC="/Volumes/ext/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2" ./configure --disable-shared --disable-crypto-dl` but I had dependencies installed in standard locations, so did not need to specify that... – sergio Jun 01 '11 at 20:26
  • I noticed that the files were partially created--but I think they're missing openssl. – Daniel Jun 01 '11 at 20:35
  • Just a thought--which version of xmlsec are you using? I had to use version 1.2.12 because it was the last one that supported libxml 2.7.3 which is the version in the iOS sdk. – Daniel Jun 01 '11 at 20:39
  • 1.2.18; tomorrow (night here), I'll try 1.2.12, if you need it. as to openssl, I find it built here: `./src/openssl/.libs/libxmlsec1-openssl.a` – sergio Jun 01 '11 at 22:10
  • I noticed that file too. But there are missing symbols from the finished product that make the OpenSSL part of xmlsec unusable. – Daniel Jun 02 '11 at 13:34
  • Daniel, this is a bit tricky. I did some tests on the symbols that were said to be missing, and they were actually there (in .a). For both libraries. E.g.: `nm -a src/.libs/libxmlsec1.a | grep _xmlSecXsltPushBin1` this will output a line where the presence of `t` or `T` means that the symbol is defined. Or: `nm -a src/openssl/.libs/libxmlsec1-openssl.a | grep xmlSecOpenSSLAppShutdown`. I think that when trying to link the binary, first an attempt is made of using shared libraries, and those are failing. `configure` is not able to link against the `.la` file, so static libraries are not found. – sergio Jun 02 '11 at 15:42
  • Continuing from above: in my case this is what happens, because I have "standard" install (macports) of openssl, libxml, etc, so the linker finds those libraries under `/opt/local/lib` and they are obviously made for x86_64. One more thing: have you checked the actual architecture of the libraries for which the linker is complaining? i.e., `lipo ../src/.libs/libxmlsec1.dylib`. and what about `lipo ../src/.libs/libxmlsec1.a`? are they i386 or x86_64? All in all, I guess that in you use `src/.libs/libxmlsec1.a` and `src/openssl/.libs/libxmlsec1-openssl.a` in your Xcode project, it will work. – sergio Jun 02 '11 at 15:44
  • Guys (@sergio and @daniel), you should know that one of the reasons the community user (bot) flags comment threads with 20+ comments in them for review is that rarely is such long discussions a good thing. Most often, important information about the question and/or answer can only be found in the comments, and many people, and certainly not search engines, read all of those. If you have important information here, please edit them into the question and/or answer. If you feel the need to discuss a question in length, there's the chat platform, link at the top of the page. Thanks. – Lasse V. Karlsen Jun 02 '11 at 15:51