gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [gnunet] branch master updated (b4f6c5a8b -> 056ca89d2)


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated (b4f6c5a8b -> 056ca89d2)
Date: Thu, 04 Jan 2018 16:08:28 +0100

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a change to branch master
in repository gnunet.

    from b4f6c5a8b motivational changes to disclaimer README.1st
     new 39981eee3 add credential
     new 691aa85bf Merge branch 'master' into credentials
     new 18f106166 - move towards verification
     new fad73f243 - add missing API; no impl
     new 3e22103e0 Merge remote-tracking branch 'origin/master' into credentials
     new 7356e4ff0 Merge remote-tracking branch 'origin/master' into credentials
     new 540d02ea8 Merge remote-tracking branch 'origin/master' into credentials
     new 299525b4d - Test commit - adding author
     new 210505951 Merge branch 'credentials' of git+ssh://gnunet.org/gnunet 
into credentials
     new 59f306e70 - fix call
     new 3664423a9 -add todos
     new 45c179757 - change record data name
     new 113150fb9 - add signatures to creds, add converter
     new 7b6f6c01a -cleanup cli tool
     new 652e112e5 Merge remote-tracking branch 'origin/master' into credentials
     new f89b1efa7 -update test
     new 6fb6ddb3c - added DLL and some checks
     new 191fd80ca Merge branch 'credentials' of git+ssh://gnunet.org/gnunet 
into credentials
     new ded88c36e Merge branch 'credentials' of git+ssh://gnunet.org/gnunet 
into credentials
     new 59f9630b8 -fix compile
     new 646723dd4 - add verify and issue to cli
     new 0f854e736 - starting backward resolution
     new fcb5ecaed -add issue test
     new 3e958fd99 -add simple test
     new ad04c24e8 -add tests
     new e2351f984 -fix verifymessage
     new 6d96eb580 - add signature to cred
     new 01fcfd11a - remove purpose from cred
     new 38153c762 Merge branch 'credentials' of git+ssh://gnunet.org/gnunet 
into credentials
     new c0ccc8d72 - minor fixes
     new a97e16efa - add better test for verification
     new 8c1425aa7 Merge branch 'credentials' of git+ssh://gnunet.org/gnunet 
into credentials
     new 10b2bbf99 -add expiration to cred
     new 97b457f5c -fix
     new 3fff08922 Merge branch 'credentials' of git+ssh://gnunet.org/gnunet 
into credentials
     new 14045cba9 -fix
     new 1be263982 - add simple verification
     new 68f5813fd - add signature check
     new 3ea628e26 -start delegation; cleanup
     new 671f7c5fb - add delegation resolution
     new b4925b163 - fix test
     new 472380f62 -add confs
     new d0f60b23e - fix; more recognizable case in test
     new 78b7c56bd - Add rest plugin for credential
     new d03ce063c -more rest
     new 490a5b645 -add parallel delegationr resolution
     new 12a3d957f -fix memleaks
     new 80bdda1c7 -add serializer
     new 8052eb644 -fix gns mq; fix serializer
     new a80e5610f -fix
     new 02066879b -towards type4
     new 745f0dc8f -fixes, prettify
     new fb662a6b5 -tests
     new 7a6a665ce -fix rest; prelim test;
     new 73a127e96 Merge remote-tracking branch 'origin/master' into credentials
     new 9c5ecc381 -refactoring
     new 33e847bf4 -fixes
     new 8ce40b5e7 -fix rest issue
     new b34ecee66 -fix
     new b0937948a -fix
     new 43b34377e Merge remote-tracking branch 'origin/master' into credentials
     new a84624407 -change api
     new d833a5528 -update rest
     new 897dd85d9 -add collect rest; fixes
     new baf9b5d76 -add tokens for credentials
     new 3c1b722a8 -fix
     new 7122f35e2 Merge remote-tracking branch 'origin/master' into credentials
     new 3cb90c74c - merge; service API change
     new 59d393a11 Merge remote-tracking branch 'origin/master' into credentials
     new ab281595e - merge with master
     new de63d9503 Merge remote-tracking branch 'origin/master' into credentials
     new 324650a2a -fix API changes
     new 80a88ff17 -fix
     new 56e4af789 -fix
     new 315cdad26 -add policy record type
     new ecb0ab123 Merge remote-tracking branch 'origin/master' into credentials
     new dfe45df6f -remove reverse record
     new 574725747 -fix idp
     new ad5b64d8e Merge remote-tracking branch 'origin/master' into credentials
     new 2d81d6d82 Merge remote-tracking branch 'origin/master' into credentials
     new d80df28d5 -fix 0-term
     new f599b93d5 Merge remote-tracking branch 'origin/master' into credentials
     new 531a89e0a -fix DEBUG output
     new ef31cd0ef Merge remote-tracking branch 'origin/master' into credentials
     new 9d601af55 -add ABE crypto module
     new 591432f73 Merge branch 'abe' into identity_abe
     new d43a25d25 -towards IdP2
     new f3a84ebcd -add serialization
     new db4e5d269 Merge branch 'abe' into identity_abe
     new de6c96ec6 -fix
     new dabca343d -fix api
     new 20d82ac39 Merge branch 'abe' into identity_abe
     new 44a176dc9 -more towards idp2
     new 271f13592 -add CLI
     new eccfb8e81 -fix
     new ae3380b0c Merge branch 'abe' into identity_abe
     new ed42d471a -add attr list
     new 32b2ebbdc -add cli
     new cfc492f5d -add free ABE functions
     new 0e13b88e8 -merge
     new 5f8b246a1 -fix
     new 075494d7b -fix leaks
     new 8119b9739 Merge branch 'abe' into identity_abe
     new 3e167b60b -fix
     new aefb30b19 Merge branch 'abe' into identity_abe
     new 811155110 -fixes
     new e2e3e2954 -fix
     new 8cb2e0da6 -fixes
     new b6755fe23 -change to gabe bswabe fork
     new 02c92c69a Merge remote-tracking branch 'origin/master' into 
identity_abe
     new 1eb75229e Merge remote-tracking branch 'origin/master' into 
identity_abe
     new 41315cebe Merge remote-tracking branch 'origin/master' into 
identity_abe
     new 9e6994a55 - Add attribute store API to IdP service
     new d5ec12fdb -move idp gns record handling to identity-provider
     new 67e0d7370 -various fixes; add attribute list API
     new 0469377fd - rework issue api
     new 7e7ada0b9 -add comments
     new 3777e05a0 -minor fixed, start consume
     new ca10195d9 -add consume API
     new 2b0c260c3 Merge remote-tracking branch 'origin/master' into 
identity_abe
     new 76817ee40 -add ticket DB for IdP
     new 1731fbd01 -fix bugs
     new 407c000bf -fix bugs
     new fc76f42d3 -add ticket iteration
     new 7807374c7 -do not persist sensitive data
     new cc838240d -remove deprecated
     new 371458b9e -revise API naming; cleanups
     new 8b22f677a -readd new rest plugin
     new 8147dd719 -fix
     new 46b73f8d1 -towards ticket revocation
     new 58d4e0f04 -more revocation
     new fd111326e -finish revocation in service, cleanup
     new bada12fb7 -fixes
     new f12a22a2a -add api impl for revocation
     new b7389bb3a -mem fixes, revocation finish
     new 6fce29c2d -fixes, add tests
     new 0729d3ff0 -fix records
     new 40fa67d02 -add new jwt handling
     new be9becc6f -add ticket listing for rest, bugfixes
     new dc7f9d7e2 -add REST revoke API
     new 0e7c1fb8f -add attribute store API, fixes
     new 037bf3d5a -fixes
     new 44f8117be -improve revocation handling
     new df344790f -fixes
     new 1cfa320f0 -bugfixes, fix memleaks
     new 0af3570c1 -add tests
     new 2d5d51340 -add consume rest api
     new c3075f180 -fix
     new 6d653d742 -fix make
     new abce261f0 -add dockerfile
     new 6f902e916 -fix docker
     new bc44eb0e6 -add docker entrypoint
     new 2edaa4ebc -add j to make
     new f431f72d9 -fixes
     new 8af95178c -fix
     new 08ea93ee6 -add stats
     new 14c62ed96 -add decrypt stats
     new a9a7ac802 -refactored
     new b16fa2d88 Merge remote-tracking branch 'origin/master' into 
identity_abe
     new f485d0399 -fix makefile
     new 02861d759 -fix
     new 24a0b84d5 -start jwt
     new 6e0922fc2 -move jwt back into idp
     new 9e486ede0 Merge remote-tracking branch 'origin/master' into 
identity_abe
     new 4b8c0ca31 Merge remote-tracking branch 'origin/master' into 
identity_abe
     new 92d8c8a77 -move idp experimental
     new 7c1f035ed -merge
     new fb85cf602 -move abe functionality out of util; prepare for release
     new 272921672 update README
     new 78705d5a4 -cleanup doc; fixes
     new 056ca89d2 Merge remote-tracking branch 'origin/identity_abe'

The 171 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 README                                             |    9 +-
 configure.ac                                       |   25 +
 contrib/Dockerfile                                 |   63 +
 contrib/docker-entrypoint.sh                       |    3 +
 po/POTFILES.in                                     |  134 +-
 src/Makefile.am                                    |   14 +-
 src/abe/Makefile.am                                |   50 +
 src/abe/abe.c                                      |  499 ++++
 src/abe/test_cpabe.c                               |   87 +
 src/credential/Makefile.am                         |  112 +
 src/credential/credential.conf.in                  |    5 +
 src/credential/credential.h                        |  221 ++
 src/credential/credential_api.c                    |  511 ++++
 src/credential/credential_misc.c                   |  168 ++
 .../credential_misc.h}                             |   38 +-
 src/credential/credential_serialization.c          |  460 +++
 src/credential/credential_serialization.h          |  159 +
 src/credential/gnunet-credential.c                 |  588 ++++
 src/credential/gnunet-service-credential.c         | 1160 ++++++++
 src/credential/plugin_gnsrecord_credential.c       |  353 +++
 src/credential/plugin_rest_credential.c            | 1146 +++++++
 src/credential/test_credential_collect.sh          |   47 +
 src/credential/test_credential_collect_rest.sh     |   90 +
 .../test_credential_defaults.conf}                 |    2 +-
 src/credential/test_credential_issue.sh            |   44 +
 src/credential/test_credential_issue_rest.sh       |   53 +
 .../test_credential_lookup.conf}                   |   13 +-
 src/credential/test_credential_verify.sh           |   81 +
 src/credential/test_credential_verify_and.sh       |   81 +
 src/credential/test_credential_verify_rest.sh      |   87 +
 src/credential/test_credential_verify_simple.sh    |   50 +
 src/exit/gnunet-daemon-exit.c                      |    2 +-
 src/gns/gns_api.c                                  |   11 +-
 src/gns/plugin_gnsrecord_gns.c                     |   67 -
 src/identity-attribute/Makefile.am                 |   44 +
 src/identity-attribute/identity_attribute.c        |  421 +++
 src/identity-attribute/identity_attribute.h        |   56 +
 .../plugin_identity_attribute_gnuid.c              |  184 ++
 src/identity-provider/Makefile.am                  |   74 +-
 src/identity-provider/gnunet-identity-token.c      |  179 --
 src/identity-provider/gnunet-idp.c                 |  439 +++
 .../gnunet-service-identity-provider.c             | 3128 +++++++++++++-------
 src/identity-provider/identity-provider.conf       |    4 +
 src/identity-provider/identity_provider.h          |  307 +-
 src/identity-provider/identity_provider_api.c      | 1213 ++++++--
 src/identity-provider/identity_token.c             |  964 ------
 src/identity-provider/identity_token.h             |  346 ---
 src/identity-provider/jwt.c                        |  180 ++
 .../plugin_gnsrecord_identity_provider.c}          |   48 +-
 .../plugin_identity_provider_sqlite.c}             |  565 ++--
 .../plugin_rest_identity_provider.c                | 1119 ++++---
 .../test_idp.conf}                                 |   15 +-
 src/identity-provider/test_idp.sh                  |   31 +
 src/identity-provider/test_idp_attribute.sh        |   40 +
 src/identity-provider/test_idp_consume.sh          |   43 +
 .../test_idp_defaults.conf}                        |    2 +-
 src/identity-provider/test_idp_issue.sh            |   42 +
 src/identity-provider/test_idp_revoke.sh           |   60 +
 src/identity/Makefile.am                           |   11 +-
 src/identity/plugin_rest_identity.c                |    3 -
 src/include/gnunet_abe_lib.h                       |  193 ++
 src/include/gnunet_credential_service.h            |  297 +-
 src/include/gnunet_gnsrecord_lib.h                 |   22 +-
 src/include/gnunet_identity_attribute_lib.h        |  277 ++
 ...plugin.h => gnunet_identity_attribute_plugin.h} |   55 +-
 src/include/gnunet_identity_provider_plugin.h      |  123 +
 src/include/gnunet_identity_provider_service.h     |  333 ++-
 src/include/gnunet_jsonapi_lib.h                   |    2 +-
 src/include/gnunet_protocols.h                     |   42 +-
 src/include/gnunet_rest_lib.h                      |    4 +-
 src/include/gnunet_rest_plugin.h                   |    2 +-
 src/include/gnunet_signatures.h                    |    5 +
 src/jsonapi/jsonapi_document.c                     |   32 +-
 src/jsonapi/jsonapi_resource.c                     |    6 +-
 src/namestore/plugin_rest_namestore.c              |   27 +-
 src/rest/rest.conf                                 |    1 +
 src/util/Makefile.am                               |    1 -
 src/util/crypto_abe.c                              |  416 +++
 78 files changed, 13567 insertions(+), 4222 deletions(-)
 create mode 100644 contrib/Dockerfile
 create mode 100644 contrib/docker-entrypoint.sh
 create mode 100644 src/abe/Makefile.am
 create mode 100644 src/abe/abe.c
 create mode 100644 src/abe/test_cpabe.c
 create mode 100644 src/credential/Makefile.am
 create mode 100644 src/credential/credential.conf.in
 create mode 100644 src/credential/credential.h
 create mode 100644 src/credential/credential_api.c
 create mode 100644 src/credential/credential_misc.c
 copy src/{include/gnunet_sensordashboard_service.h => 
credential/credential_misc.h} (59%)
 create mode 100644 src/credential/credential_serialization.c
 create mode 100644 src/credential/credential_serialization.h
 create mode 100644 src/credential/gnunet-credential.c
 create mode 100644 src/credential/gnunet-service-credential.c
 create mode 100644 src/credential/plugin_gnsrecord_credential.c
 create mode 100644 src/credential/plugin_rest_credential.c
 create mode 100755 src/credential/test_credential_collect.sh
 create mode 100755 src/credential/test_credential_collect_rest.sh
 copy src/{gns/test_gns_defaults.conf => 
credential/test_credential_defaults.conf} (87%)
 create mode 100755 src/credential/test_credential_issue.sh
 create mode 100755 src/credential/test_credential_issue_rest.sh
 copy src/{gns/test_gns_lookup.conf => credential/test_credential_lookup.conf} 
(54%)
 create mode 100755 src/credential/test_credential_verify.sh
 create mode 100755 src/credential/test_credential_verify_and.sh
 create mode 100755 src/credential/test_credential_verify_rest.sh
 create mode 100755 src/credential/test_credential_verify_simple.sh
 create mode 100644 src/identity-attribute/Makefile.am
 create mode 100644 src/identity-attribute/identity_attribute.c
 create mode 100644 src/identity-attribute/identity_attribute.h
 create mode 100644 src/identity-attribute/plugin_identity_attribute_gnuid.c
 delete mode 100644 src/identity-provider/gnunet-identity-token.c
 create mode 100644 src/identity-provider/gnunet-idp.c
 delete mode 100644 src/identity-provider/identity_token.c
 delete mode 100644 src/identity-provider/identity_token.h
 create mode 100644 src/identity-provider/jwt.c
 rename src/{identity/plugin_gnsrecord_identity.c => 
identity-provider/plugin_gnsrecord_identity_provider.c} (81%)
 copy src/{namestore/plugin_namestore_sqlite.c => 
identity-provider/plugin_identity_provider_sqlite.c} (50%)
 copy src/{gns/test_gns_lookup.conf => identity-provider/test_idp.conf} (51%)
 create mode 100755 src/identity-provider/test_idp.sh
 create mode 100755 src/identity-provider/test_idp_attribute.sh
 create mode 100755 src/identity-provider/test_idp_consume.sh
 copy src/{gns/test_gns_defaults.conf => 
identity-provider/test_idp_defaults.conf} (88%)
 create mode 100755 src/identity-provider/test_idp_issue.sh
 create mode 100755 src/identity-provider/test_idp_revoke.sh
 create mode 100644 src/include/gnunet_abe_lib.h
 create mode 100644 src/include/gnunet_identity_attribute_lib.h
 copy src/include/{gnunet_gnsrecord_plugin.h => 
gnunet_identity_attribute_plugin.h} (69%)
 create mode 100644 src/include/gnunet_identity_provider_plugin.h
 create mode 100644 src/util/crypto_abe.c

diff --git a/README b/README
index db64bc17a..ef30fe7e3 100644
--- a/README
+++ b/README
@@ -15,8 +15,11 @@ GNU package (http://www.gnu.org/).
 This is an ALPHA release.  There are known and significant bugs as
 well as many missing features in this release.
 
+GNUnet is free software released under the GNU General Public License
+(v3 or later). For details see the COPYING file in this directory.
+
 Additional documentation about GNUnet can be found at
-https://gnunet.org/.
+https://gnunet.org/ and in the doc/ folder.
 
 
 Dependencies:
@@ -63,6 +66,8 @@ How to install?
 The fastest way is to use a binary package if it is available for your
 system.  For a more detailed description, read the installation
 instructions on the webpage at https://gnunet.org/installation.
+Generic installation instructions are in the INSTALL file in this
+directory.
 
 Note that some functions of GNUnet require "root" access.  GNUnet will
 install (tiny) SUID binaries for those functions is you run "make
@@ -300,7 +305,7 @@ Stay tuned
 
 * https://gnunet.org/
 * https://gnunet.org/bugs/
-* https://gnunet.org/svn/
+* https://gnunet.org/git/
 * http://www.gnu.org/software/gnunet/
 * http://mail.gnu.org/mailman/listinfo/gnunet-developers
 * http://mail.gnu.org/mailman/listinfo/help-gnunet
diff --git a/configure.ac b/configure.ac
index eae03b01b..017b4836c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -446,6 +446,27 @@ AC_CHECK_LIB(ogg, ogg_stream_flush_fill,
         ogg=0)
 
 
+PKG_CHECK_MODULES([GLIB], [glib-2.0])
+# check for pbc library
+pbc=0
+AC_CHECK_HEADER([pbc/pbc.h],pbc=1)
+AC_CHECK_HEADER([gabe.h],abe=1)
+AM_CONDITIONAL(HAVE_PBC, [test "$pbc" = 1])
+AM_CONDITIONAL(HAVE_ABE, [test "$abe" = 1])
+if test "x$pbc" = x1
+then
+  AC_DEFINE([HAVE_PBC],[1],[Have pbc library])
+else
+  AC_DEFINE([HAVE_PBC],[0],[Lacking pbc library])
+fi
+if test "x$abe" = x1
+then
+  AC_DEFINE([HAVE_ABE],[1],[Have ABE library])
+else
+  AC_DEFINE([HAVE_ABE],[0],[Lacking ABE library])
+fi
+
+
 
 gst=0
 PKG_CHECK_MODULES(
@@ -1570,6 +1591,8 @@ src/gnsrecord/Makefile
 src/hello/Makefile
 src/identity/Makefile
 src/identity/identity.conf
+src/credential/Makefile
+src/credential/credential.conf
 src/include/Makefile
 src/integration-tests/Makefile
 src/json/Makefile
@@ -1635,6 +1658,8 @@ src/vpn/vpn.conf
 src/zonemaster/Makefile
 src/zonemaster/zonemaster.conf
 src/rest/Makefile
+src/abe/Makefile
+src/identity-attribute/Makefile
 src/identity-provider/Makefile
 pkgconfig/Makefile
 pkgconfig/gnunetarm.pc
diff --git a/contrib/Dockerfile b/contrib/Dockerfile
new file mode 100644
index 000000000..5a193a46d
--- /dev/null
+++ b/contrib/Dockerfile
@@ -0,0 +1,63 @@
+from fedora:26
+
+# Install the required build tools
+RUN dnf -y update && dnf -y install which git automake texinfo gettext-devel 
autoconf libtool libtool-ltdl-devel libidn-devel libunistring-devel glpk 
libextractor-devel libmicrohttpd-devel gnutls libgcrypt-devel jansson-devel 
sqlite-devel npm
+
+WORKDIR /usr/src
+
+# Install gnurl from source at version gnurl-7.54.0
+RUN git clone https://git.taler.net/gnurl.git --branch gnurl-7.54.0
+WORKDIR /usr/src/gnurl
+RUN autoreconf -i
+RUN ./configure --enable-ipv6 --with-gnutls --without-libssh2 \
+--without-libmetalink --without-winidn --without-librtmp \
+--without-nghttp2 --without-nss --without-cyassl \
+--without-polarssl --without-ssl --without-winssl \
+--without-darwinssl --disable-sspi --disable-ntlm-wb --disable-ldap \
+--disable-rtsp --disable-dict --disable-telnet --disable-tftp \
+--disable-pop3 --disable-imap --disable-smtp --disable-gopher \
+--disable-file --disable-ftp --disable-smb
+RUN make install
+WORKDIR /usr/src
+
+RUN dnf -y install wget flex bison
+
+# Install libpbc
+RUN wget https://crypto.stanford.edu/pbc/files/pbc-0.5.14.tar.gz
+RUN tar xvzpf pbc-0.5.14.tar.gz
+WORKDIR /usr/src/pbc-0.5.14
+RUN ./configure --prefix=/usr
+RUN make install
+WORKDIR /usr/src
+
+RUN dnf -y install glib2-devel
+
+# Install libbswabe
+RUN git clone https://github.com/schanzen/libgabe.git
+WORKDIR /usr/src/libgabe
+RUN ./configure --prefix=/usr
+RUN make install
+
+# Install WebUI
+WORKDIR /usr/src/
+RUN git clone https://github.com/schanzen/gnunet-webui.git
+WORKDIR /usr/src/gnunet-webui
+RUN git checkout gnuidentity
+
+RUN mkdir /usr/src/gnunet
+WORKDIR /usr/src/gnunet
+ADD . .
+ARG NUM_JOBS
+RUN ./bootstrap
+RUN ./configure --prefix=/usr/local
+RUN make -j$NUM_JOBS
+RUN make install
+
+RUN groupadd gnunetdns
+RUN adduser --system -m --home-dir /var/lib/gnunet gnunet
+RUN chown gnunet:gnunet /var/lib/gnunet
+RUN echo '[arm]\nSYSTEM_ONLY = YES\nUSER_ONLY = NO\n' > /etc/gnunet.conf
+
+ADD docker-entrypoint.sh .
+
+CMD ["sh", "docker-entrypoint.sh"] 
diff --git a/contrib/docker-entrypoint.sh b/contrib/docker-entrypoint.sh
new file mode 100644
index 000000000..807d86d6f
--- /dev/null
+++ b/contrib/docker-entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+gnunet-arm -s > $HOME/gnunet.log 2>&1
+exec bash
\ No newline at end of file
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4a4cfbd96..2fcb74c09 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,15 +1,24 @@
+src/abe/abe.c
 src/arm/arm_api.c
 src/arm/arm_monitor_api.c
 src/arm/gnunet-arm.c
 src/arm/gnunet-service-arm.c
 src/arm/mockup-service.c
+src/ats-tests/ats-testing-experiment.c
+src/ats-tests/ats-testing-log.c
+src/ats-tests/ats-testing-preferences.c
+src/ats-tests/ats-testing-traffic.c
+src/ats-tests/ats-testing.c
+src/ats-tests/gnunet-ats-sim.c
+src/ats-tests/gnunet-solver-eval.c
+src/ats-tool/gnunet-ats.c
 src/ats/ats_api_connectivity.c
 src/ats/ats_api_performance.c
 src/ats/ats_api_scanner.c
 src/ats/ats_api_scheduling.c
 src/ats/gnunet-ats-solver-eval.c
-src/ats/gnunet-service-ats_addresses.c
 src/ats/gnunet-service-ats.c
+src/ats/gnunet-service-ats_addresses.c
 src/ats/gnunet-service-ats_connectivity.c
 src/ats/gnunet-service-ats_normalization.c
 src/ats/gnunet-service-ats_performance.c
@@ -20,14 +29,6 @@ src/ats/gnunet-service-ats_scheduling.c
 src/ats/plugin_ats_mlp.c
 src/ats/plugin_ats_proportional.c
 src/ats/plugin_ats_ril.c
-src/ats-tests/ats-testing.c
-src/ats-tests/ats-testing-experiment.c
-src/ats-tests/ats-testing-log.c
-src/ats-tests/ats-testing-preferences.c
-src/ats-tests/ats-testing-traffic.c
-src/ats-tests/gnunet-ats-sim.c
-src/ats-tests/gnunet-solver-eval.c
-src/ats-tool/gnunet-ats.c
 src/auction/gnunet-auction-create.c
 src/auction/gnunet-auction-info.c
 src/auction/gnunet-auction-join.c
@@ -39,8 +40,8 @@ src/block/plugin_block_test.c
 src/cadet/cadet_api.c
 src/cadet/cadet_test_lib.c
 src/cadet/desirability_table.c
-src/cadet/gnunet-cadet.c
 src/cadet/gnunet-cadet-profiler.c
+src/cadet/gnunet-cadet.c
 src/cadet/gnunet-service-cadet.c
 src/cadet/gnunet-service-cadet_channel.c
 src/cadet/gnunet-service-cadet_connection.c
@@ -56,15 +57,15 @@ src/consensus/gnunet-service-consensus.c
 src/consensus/plugin_block_consensus.c
 src/conversation/conversation_api.c
 src/conversation/conversation_api_call.c
-src/conversation/gnunet-conversation.c
 src/conversation/gnunet-conversation-test.c
-src/conversation/gnunet_gst.c
-src/conversation/gnunet_gst_test.c
-src/conversation/gnunet-helper-audio-playback.c
+src/conversation/gnunet-conversation.c
 src/conversation/gnunet-helper-audio-playback-gst.c
-src/conversation/gnunet-helper-audio-record.c
+src/conversation/gnunet-helper-audio-playback.c
 src/conversation/gnunet-helper-audio-record-gst.c
+src/conversation/gnunet-helper-audio-record.c
 src/conversation/gnunet-service-conversation.c
+src/conversation/gnunet_gst.c
+src/conversation/gnunet_gst_test.c
 src/conversation/microphone.c
 src/conversation/plugin_gnsrecord_conversation.c
 src/conversation/speaker.c
@@ -75,6 +76,13 @@ src/core/gnunet-service-core.c
 src/core/gnunet-service-core_kx.c
 src/core/gnunet-service-core_sessions.c
 src/core/gnunet-service-core_typemap.c
+src/credential/credential_api.c
+src/credential/credential_misc.c
+src/credential/credential_serialization.c
+src/credential/gnunet-credential.c
+src/credential/gnunet-service-credential.c
+src/credential/plugin_gnsrecord_credential.c
+src/credential/plugin_rest_credential.c
 src/curl/curl.c
 src/curl/curl_reschedule.c
 src/datacache/datacache.c
@@ -94,7 +102,6 @@ src/dht/dht_api.c
 src/dht/dht_test_lib.c
 src/dht/gnunet-dht-get.c
 src/dht/gnunet-dht-monitor.c
-src/dht/gnunet_dht_profiler.c
 src/dht/gnunet-dht-put.c
 src/dht/gnunet-service-dht.c
 src/dht/gnunet-service-dht_clients.c
@@ -103,6 +110,7 @@ src/dht/gnunet-service-dht_hello.c
 src/dht/gnunet-service-dht_neighbours.c
 src/dht/gnunet-service-dht_nse.c
 src/dht/gnunet-service-dht_routing.c
+src/dht/gnunet_dht_profiler.c
 src/dht/plugin_block_dht.c
 src/dns/dns_api.c
 src/dns/dnsparser.c
@@ -117,8 +125,8 @@ src/dv/gnunet-dv.c
 src/dv/gnunet-service-dv.c
 src/dv/plugin_transport_dv.c
 src/exit/gnunet-daemon-exit.c
-src/exit/gnunet-helper-exit.c
 src/exit/gnunet-helper-exit-windows.c
+src/exit/gnunet-helper-exit.c
 src/fragmentation/defragmentation.c
 src/fragmentation/fragmentation.c
 src/fs/fs_api.c
@@ -143,8 +151,8 @@ src/fs/gnunet-auto-share.c
 src/fs/gnunet-daemon-fsprofiler.c
 src/fs/gnunet-directory.c
 src/fs/gnunet-download.c
-src/fs/gnunet-fs.c
 src/fs/gnunet-fs-profiler.c
+src/fs/gnunet-fs.c
 src/fs/gnunet-helper-fs-publish.c
 src/fs/gnunet-publish.c
 src/fs/gnunet-search.c
@@ -162,10 +170,10 @@ src/fs/plugin_block_fs.c
 src/gns/gns_api.c
 src/gns/gnunet-bcd.c
 src/gns/gnunet-dns2gns.c
-src/gns/gnunet-gns.c
 src/gns/gnunet-gns-helper-service-w32.c
 src/gns/gnunet-gns-import.c
 src/gns/gnunet-gns-proxy.c
+src/gns/gnunet-gns.c
 src/gns/gnunet-service-gns.c
 src/gns/gnunet-service-gns_interceptor.c
 src/gns/gnunet-service-gns_resolver.c
@@ -174,41 +182,44 @@ src/gns/nss/nss_gns_query.c
 src/gns/plugin_block_gns.c
 src/gns/plugin_gnsrecord_gns.c
 src/gns/plugin_rest_gns.c
+src/gns/w32nsp-install.c
+src/gns/w32nsp-resolve.c
+src/gns/w32nsp-uninstall.c
+src/gns/w32nsp.c
 src/gnsrecord/gnsrecord.c
 src/gnsrecord/gnsrecord_crypto.c
 src/gnsrecord/gnsrecord_misc.c
 src/gnsrecord/gnsrecord_serialization.c
 src/gnsrecord/plugin_gnsrecord_dns.c
-src/gns/w32nsp.c
-src/gns/w32nsp-install.c
-src/gns/w32nsp-resolve.c
-src/gns/w32nsp-uninstall.c
 src/hello/address.c
 src/hello/gnunet-hello.c
 src/hello/hello.c
 src/hostlist/gnunet-daemon-hostlist.c
 src/hostlist/gnunet-daemon-hostlist_client.c
 src/hostlist/gnunet-daemon-hostlist_server.c
+src/identity-attribute/identity_attribute.c
+src/identity-attribute/plugin_identity_attribute_gnuid.c
+src/identity-provider/gnunet-idp.c
+src/identity-provider/gnunet-service-identity-provider.c
+src/identity-provider/identity_provider_api.c
+src/identity-provider/jwt.c
+src/identity-provider/plugin_gnsrecord_identity_provider.c
+src/identity-provider/plugin_identity_provider_sqlite.c
+src/identity-provider/plugin_rest_identity_provider.c
 src/identity/gnunet-identity.c
 src/identity/gnunet-service-identity.c
 src/identity/identity_api.c
 src/identity/identity_api_lookup.c
-src/identity/plugin_gnsrecord_identity.c
 src/identity/plugin_rest_identity.c
-src/identity-provider/gnunet-identity-token.c
-src/identity-provider/gnunet-service-identity-provider.c
-src/identity-provider/identity_provider_api.c
-src/identity-provider/identity_token.c
-src/identity-provider/plugin_rest_identity_provider.c
+src/json/json.c
+src/json/json_generator.c
+src/json/json_helper.c
+src/json/json_mhd.c
 src/jsonapi/jsonapi.c
 src/jsonapi/jsonapi_document.c
 src/jsonapi/jsonapi_error.c
 src/jsonapi/jsonapi_relationship.c
 src/jsonapi/jsonapi_resource.c
-src/json/json.c
-src/json/json_generator.c
-src/json/json_helper.c
-src/json/json_mhd.c
 src/multicast/gnunet-multicast.c
 src/multicast/gnunet-service-multicast.c
 src/multicast/multicast_api.c
@@ -222,8 +233,8 @@ src/namecache/namecache_api.c
 src/namecache/plugin_namecache_flat.c
 src/namecache/plugin_namecache_postgres.c
 src/namecache/plugin_namecache_sqlite.c
-src/namestore/gnunet-namestore.c
 src/namestore/gnunet-namestore-fcfsd.c
+src/namestore/gnunet-namestore.c
 src/namestore/gnunet-service-namestore.c
 src/namestore/namestore_api.c
 src/namestore/namestore_api_monitor.c
@@ -238,10 +249,10 @@ src/nat-auto/gnunet-service-nat-auto.c
 src/nat-auto/gnunet-service-nat-auto_legacy.c
 src/nat-auto/nat_auto_api.c
 src/nat-auto/nat_auto_api_test.c
-src/nat/gnunet-helper-nat-client.c
 src/nat/gnunet-helper-nat-client-windows.c
-src/nat/gnunet-helper-nat-server.c
+src/nat/gnunet-helper-nat-client.c
 src/nat/gnunet-helper-nat-server-windows.c
+src/nat/gnunet-helper-nat-server.c
 src/nat/gnunet-nat.c
 src/nat/gnunet-service-nat.c
 src/nat/gnunet-service-nat_externalip.c
@@ -250,15 +261,15 @@ src/nat/gnunet-service-nat_mini.c
 src/nat/gnunet-service-nat_stun.c
 src/nat/nat_api.c
 src/nat/nat_api_stun.c
-src/nse/gnunet-nse.c
 src/nse/gnunet-nse-profiler.c
+src/nse/gnunet-nse.c
 src/nse/gnunet-service-nse.c
 src/nse/nse_api.c
+src/peerinfo-tool/gnunet-peerinfo.c
+src/peerinfo-tool/gnunet-peerinfo_plugins.c
 src/peerinfo/gnunet-service-peerinfo.c
 src/peerinfo/peerinfo_api.c
 src/peerinfo/peerinfo_api_notify.c
-src/peerinfo-tool/gnunet-peerinfo.c
-src/peerinfo-tool/gnunet-peerinfo_plugins.c
 src/peerstore/gnunet-peerstore.c
 src/peerstore/gnunet-service-peerstore.c
 src/peerstore/peerstore_api.c
@@ -309,13 +320,13 @@ src/rps/gnunet-service-rps_custommap.c
 src/rps/gnunet-service-rps_sampler.c
 src/rps/gnunet-service-rps_sampler_elem.c
 src/rps/gnunet-service-rps_view.c
-src/rps/rps_api.c
 src/rps/rps-test_util.c
+src/rps/rps_api.c
 src/scalarproduct/gnunet-scalarproduct.c
-src/scalarproduct/gnunet-service-scalarproduct_alice.c
-src/scalarproduct/gnunet-service-scalarproduct_bob.c
 src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
 src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
+src/scalarproduct/gnunet-service-scalarproduct_alice.c
+src/scalarproduct/gnunet-service-scalarproduct_bob.c
 src/scalarproduct/scalarproduct_api.c
 src/secretsharing/gnunet-secretsharing-profiler.c
 src/secretsharing/gnunet-service-secretsharing.c
@@ -342,15 +353,16 @@ src/statistics/gnunet-statistics.c
 src/statistics/statistics_api.c
 src/template/gnunet-service-template.c
 src/template/gnunet-template.c
+src/testbed-logger/gnunet-service-testbed-logger.c
+src/testbed-logger/testbed_logger_api.c
 src/testbed/generate-underlay-topology.c
 src/testbed/gnunet-daemon-latency-logger.c
 src/testbed/gnunet-daemon-testbed-blacklist.c
 src/testbed/gnunet-daemon-testbed-underlay.c
 src/testbed/gnunet-helper-testbed.c
-src/testbed/gnunet_mpi_test.c
 src/testbed/gnunet-service-test-barriers.c
-src/testbed/gnunet-service-testbed_barriers.c
 src/testbed/gnunet-service-testbed.c
+src/testbed/gnunet-service-testbed_barriers.c
 src/testbed/gnunet-service-testbed_cache.c
 src/testbed/gnunet-service-testbed_connectionpool.c
 src/testbed/gnunet-service-testbed_cpustatus.c
@@ -358,20 +370,19 @@ src/testbed/gnunet-service-testbed_links.c
 src/testbed/gnunet-service-testbed_meminfo.c
 src/testbed/gnunet-service-testbed_oc.c
 src/testbed/gnunet-service-testbed_peers.c
-src/testbed/gnunet_testbed_mpi_spawn.c
 src/testbed/gnunet-testbed-profiler.c
-src/testbed-logger/gnunet-service-testbed-logger.c
-src/testbed-logger/testbed_logger_api.c
-src/testbed/testbed_api_barriers.c
+src/testbed/gnunet_mpi_test.c
+src/testbed/gnunet_testbed_mpi_spawn.c
 src/testbed/testbed_api.c
+src/testbed/testbed_api_barriers.c
 src/testbed/testbed_api_hosts.c
 src/testbed/testbed_api_operations.c
 src/testbed/testbed_api_peers.c
 src/testbed/testbed_api_sd.c
 src/testbed/testbed_api_services.c
 src/testbed/testbed_api_statistics.c
-src/testbed/testbed_api_testbed.c
 src/testbed/testbed_api_test.c
+src/testbed/testbed_api_testbed.c
 src/testbed/testbed_api_topology.c
 src/testbed/testbed_api_underlay.c
 src/testing/gnunet-testing.c
@@ -380,34 +391,39 @@ src/testing/testing.c
 src/topology/friends.c
 src/topology/gnunet-daemon-topology.c
 src/transport/gnunet-helper-transport-bluetooth.c
-src/transport/gnunet-helper-transport-wlan.c
 src/transport/gnunet-helper-transport-wlan-dummy.c
-src/transport/gnunet-service-transport_ats.c
+src/transport/gnunet-helper-transport-wlan.c
 src/transport/gnunet-service-transport.c
+src/transport/gnunet-service-transport_ats.c
 src/transport/gnunet-service-transport_hello.c
 src/transport/gnunet-service-transport_manipulation.c
 src/transport/gnunet-service-transport_neighbours.c
 src/transport/gnunet-service-transport_plugins.c
 src/transport/gnunet-service-transport_validation.c
-src/transport/gnunet-transport.c
 src/transport/gnunet-transport-certificate-creation.c
 src/transport/gnunet-transport-profiler.c
 src/transport/gnunet-transport-wlan-receiver.c
 src/transport/gnunet-transport-wlan-sender.c
+src/transport/gnunet-transport.c
 src/transport/plugin_transport_http_client.c
 src/transport/plugin_transport_http_common.c
 src/transport/plugin_transport_http_server.c
 src/transport/plugin_transport_smtp.c
 src/transport/plugin_transport_tcp.c
 src/transport/plugin_transport_template.c
-src/transport/plugin_transport_udp_broadcasting.c
 src/transport/plugin_transport_udp.c
+src/transport/plugin_transport_udp_broadcasting.c
 src/transport/plugin_transport_unix.c
 src/transport/plugin_transport_wlan.c
 src/transport/tcp_connection_legacy.c
 src/transport/tcp_server_legacy.c
 src/transport/tcp_server_mst_legacy.c
 src/transport/tcp_service_legacy.c
+src/transport/transport-testing-filenames.c
+src/transport/transport-testing-loggers.c
+src/transport/transport-testing-main.c
+src/transport/transport-testing-send.c
+src/transport/transport-testing.c
 src/transport/transport_api_address_to_string.c
 src/transport/transport_api_blacklist.c
 src/transport/transport_api_core.c
@@ -416,11 +432,6 @@ src/transport/transport_api_manipulation.c
 src/transport/transport_api_monitor_peers.c
 src/transport/transport_api_monitor_plugins.c
 src/transport/transport_api_offer_hello.c
-src/transport/transport-testing.c
-src/transport/transport-testing-filenames.c
-src/transport/transport-testing-loggers.c
-src/transport/transport-testing-main.c
-src/transport/transport-testing-send.c
 src/tun/regex.c
 src/tun/tun.c
 src/util/bandwidth.c
@@ -434,10 +445,11 @@ src/util/configuration_loader.c
 src/util/container_bloomfilter.c
 src/util/container_heap.c
 src/util/container_meta_data.c
-src/util/container_multihashmap32.c
 src/util/container_multihashmap.c
+src/util/container_multihashmap32.c
 src/util/container_multipeermap.c
 src/util/container_multishortmap.c
+src/util/crypto_abe.c
 src/util/crypto_crc.c
 src/util/crypto_ecc.c
 src/util/crypto_ecc_dlog.c
@@ -454,8 +466,8 @@ src/util/crypto_symmetric.c
 src/util/disk.c
 src/util/getopt.c
 src/util/getopt_helpers.c
-src/util/gnunet-config.c
 src/util/gnunet-config-diff.c
+src/util/gnunet-config.c
 src/util/gnunet-ecc.c
 src/util/gnunet-helper-w32-console.c
 src/util/gnunet-resolver.c
@@ -486,8 +498,8 @@ src/util/time.c
 src/util/w32cat.c
 src/util/win.c
 src/util/winproc.c
-src/vpn/gnunet-helper-vpn.c
 src/vpn/gnunet-helper-vpn-windows.c
+src/vpn/gnunet-helper-vpn.c
 src/vpn/gnunet-service-vpn.c
 src/vpn/gnunet-vpn.c
 src/vpn/vpn_api.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7f1a00177..6d0284157 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,11 +12,12 @@ endif
 if HAVE_EXPERIMENTAL
  EXP_DIR = \
   rps
-endif
-
-if HAVE_JSON
-if HAVE_MHD
-  PROVIDER_DIR = identity-provider
+#  dv (FTBFS)
+if HAVE_ABE
+  EXP_DIR += abe \
+                                                credential \
+                  identity-attribute \
+                                                identity-provider 
 endif
 endif
 
@@ -128,7 +129,6 @@ SUBDIRS = \
   psyc \
   social \
   $(AUCTION_DIR) \
-  $(EXP_DIR) \
-  $(PROVIDER_DIR)
+  $(EXP_DIR)
 
 endif
diff --git a/src/abe/Makefile.am b/src/abe/Makefile.am
new file mode 100644
index 000000000..308e6c67c
--- /dev/null
+++ b/src/abe/Makefile.am
@@ -0,0 +1,50 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+dist_pkgcfg_DATA = \
+  abe.conf
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIB = -lgcov
+endif
+
+libgnunetabe_la_SOURCES = abe.c 
+
+libgnunetabe_la_LIBADD = \
+  $(GCLIBADD)\
+  $(LIBGCRYPT_LIBS) \
+  $(LTLIBICONV) \
+  $(LTLIBINTL) \
+       $(ABE_LIBADD) \
+       -lgabe \
+       -lpbc \
+       -lglib-2.0 \
+  -lltdl $(Z_LIBS) -lunistring $(XLIB)
+
+libgnunetabe_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS) \
+  -version-info 1:0:0
+
+lib_LTLIBRARIES = libgnunetabe.la
+
+if ENABLE_TEST_RUN
+AM_TESTS_ENVIRONMENT=export 
GNUNET_PREFIX=$${GNUNET_PREFIX:address@hidden@};export 
PATH=$${GNUNET_PREFIX:address@hidden@}/bin:$$PATH;unset XDG_DATA_HOME;unset 
XDG_CONFIG_HOME;
+TESTS = $(check_PROGRAMS)
+endif
+
+check_PROGRAMS = test_cpabe 
+
+test_cpabe_SOURCES = \
+ test_cpabe.c
+test_cpabe_LDADD = \
+ libgnunetabe.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+check_PROGRAMS += \
+ test_cpabe
diff --git a/src/abe/abe.c b/src/abe/abe.c
new file mode 100644
index 000000000..3f1f6dc5b
--- /dev/null
+++ b/src/abe/abe.c
@@ -0,0 +1,499 @@
+/*
+     This file is part of GNUnet.  Copyright (C) 2001-2018 Christian Grothoff
+     (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+
+*/
+
+/**
+ * @file abe/abe.c
+ * @brief functions for Attribute-Based Encryption
+ * @author Martin Schanzenbach
+ */
+
+
+#include "platform.h"
+#include <pbc/pbc.h>
+#include <gabe.h>
+
+#include "gnunet_crypto_lib.h"
+#include "gnunet_abe_lib.h"
+
+struct GNUNET_ABE_AbeMasterKey
+{
+  gabe_pub_t* pub;
+  gabe_msk_t* msk;
+};
+
+struct GNUNET_ABE_AbeKey
+{
+  gabe_pub_t* pub;
+  gabe_prv_t* prv;
+};
+
+static int
+init_aes( element_t k, int enc,
+          gcry_cipher_hd_t* handle,
+          struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+          unsigned char* iv)
+{
+  int rc;
+  int key_len;
+  unsigned char* key_buf;
+  
+  key_len = element_length_in_bytes(k) < 33 ? 3 : element_length_in_bytes(k);
+  key_buf = (unsigned char*) malloc(key_len);
+  element_to_bytes(key_buf, k);
+
+  memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH); 
+  GNUNET_assert (0 ==
+                 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
+                                   GCRY_CIPHER_MODE_CFB, 0));
+  rc = gcry_cipher_setkey (*handle,
+                           key->aes_key,
+                           sizeof (key->aes_key));
+  GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+  memset (iv, 0, 16); //TODO make reasonable
+  rc = gcry_cipher_setiv (*handle,
+                          iv,
+                          16);
+  GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+
+  free(key_buf);
+  return rc;
+}
+
+static int
+aes_128_cbc_encrypt( char* pt,
+                     int size,
+                     element_t k,
+                     char **ct )
+{
+  gcry_cipher_hd_t handle;
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  unsigned char iv[16];
+  char* buf;
+  int padding;
+  int buf_size;
+  uint8_t len[4];
+  init_aes(k, 1, &handle, &skey, iv);
+
+  /* TODO make less crufty */
+
+  /* stuff in real length (big endian) before padding */
+  len[0] = (size & 0xff000000)>>24;
+  len[1] = (size & 0xff0000)>>16;
+  len[2] = (size & 0xff00)>>8;
+  len[3] = (size & 0xff)>>0;
+  padding = 16 - ((4+size) % 16);
+  buf_size = 4 + size + padding;
+  buf = GNUNET_malloc (buf_size);
+  GNUNET_memcpy (buf, len, 4);
+  GNUNET_memcpy (buf+4, pt, size);
+  *ct = GNUNET_malloc (buf_size);
+
+  GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf, 
buf_size));
+  gcry_cipher_close (handle);
+  //AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
+  GNUNET_free (buf);
+  return buf_size;
+}
+
+static int
+aes_128_cbc_decrypt( char* ct,
+                     int size,
+                     element_t k,
+                     char **pt )
+{
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  gcry_cipher_hd_t handle;
+  unsigned char iv[16];
+  char* tmp;
+  uint32_t len;
+  
+  init_aes(k, 1, &handle, &skey, iv);
+
+  tmp = GNUNET_malloc (size);
+
+  //AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
+  GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size)); 
+  gcry_cipher_close (handle);
+  /* TODO make less crufty */
+  
+  /* get real length */
+  len = 0;
+  len = len
+    | ((tmp[0])<<24) | ((tmp[1])<<16)
+    | ((tmp[2])<<8)  | ((tmp[3])<<0);
+  /* truncate any garbage from the padding */
+  *pt = GNUNET_malloc (len);
+  GNUNET_memcpy (*pt, tmp+4, len);
+  GNUNET_free (tmp);
+  return len;
+}
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE master key. Caller must free return value.
+ *
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
+ */
+struct GNUNET_ABE_AbeMasterKey*
+GNUNET_ABE_cpabe_create_master_key (void)
+{
+  struct GNUNET_ABE_AbeMasterKey* key;
+  key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
+  gabe_setup(&key->pub, &key->msk);
+  GNUNET_assert (NULL != key->pub);
+  GNUNET_assert (NULL != key->msk);
+  return key;
+}
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE master key.
+ *
+ * @param key the master key
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key)
+{
+  gabe_msk_free (key->msk);
+  gabe_pub_free (key->pub);
+  //GNUNET_free (key->msk);
+  //gabe_msk_free (key->msk); //For some reason free of pub implicit?
+  GNUNET_free (key);
+}
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE key. Caller must free return value.
+ *
+ * @param key the master key
+ * @param attrs the attributes to append to the key
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
+ */
+struct GNUNET_ABE_AbeKey*
+GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
+                             char **attrs)
+{
+  struct GNUNET_ABE_AbeKey *prv_key;
+  int size;
+  char *tmp;
+  
+  prv_key = GNUNET_new (struct GNUNET_ABE_AbeKey);
+  prv_key->prv = gabe_keygen(key->pub, key->msk, attrs);
+  size = gabe_pub_serialize(key->pub, &tmp);
+  prv_key->pub = gabe_pub_unserialize(tmp, size);
+  GNUNET_free (tmp);
+  GNUNET_assert (NULL != prv_key->prv);
+  return prv_key;
+}
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE key.
+ *
+ * @param key the key to delete
+ * @param delete_pub GNUNE_YES if the public key should also be freed (bug in 
gabe)
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
+                                int delete_pub)
+{
+  //Memory management in gabe is buggy
+  gabe_prv_free (key->prv);
+  if (GNUNET_YES == delete_pub)
+    gabe_pub_free (key->pub);
+  GNUNET_free (key);
+}
+
+static ssize_t
+write_cpabe (void **result,
+             uint32_t file_len,
+             char* cph_buf,
+             int cph_buf_len,
+             char* aes_buf,
+             int aes_buf_len)
+{
+  char *ptr;
+  uint32_t *len;
+  
+  *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
+  ptr = *result;
+  len = (uint32_t*) ptr;
+  *len = htonl (file_len);
+  ptr += 4;
+  len = (uint32_t*) ptr;
+  *len = htonl (aes_buf_len);
+  ptr += 4;
+  memcpy (ptr, aes_buf, aes_buf_len);
+  ptr += aes_buf_len;
+  len = (uint32_t*) ptr;
+  *len = htonl (cph_buf_len);
+  ptr += 4;
+  memcpy (ptr, cph_buf, cph_buf_len);
+  return 12 + cph_buf_len + aes_buf_len;
+}
+
+static ssize_t
+read_cpabe (const void *data,
+            char** cph_buf,
+            int *cph_buf_len,
+            char** aes_buf,
+            int *aes_buf_len)
+{
+  int buf_len;
+  char *ptr;
+  uint32_t *len;
+
+  ptr = (char*)data;
+  len = (uint32_t*)ptr;
+  buf_len = ntohl (*len);
+  ptr += 4;
+  len = (uint32_t*)ptr;
+  *aes_buf_len = ntohl (*len);
+  ptr += 4;
+  *aes_buf = GNUNET_malloc (*aes_buf_len);
+  memcpy(*aes_buf, ptr, *aes_buf_len);
+  ptr += *aes_buf_len;
+  len = (uint32_t*)ptr;
+  *cph_buf_len = ntohl (*len);
+  ptr += 4;
+  *cph_buf = GNUNET_malloc (*cph_buf_len);
+  memcpy(*cph_buf, ptr, *cph_buf_len);
+
+  return buf_len;
+}
+
+/**
+ * @ingroup abe
+ * Encrypt a block using  sessionkey.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param policy the ABE policy
+ * @param key the key used to encrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_encrypt (const void *block,
+                             size_t size,
+                             const char *policy,
+                             const struct GNUNET_ABE_AbeMasterKey *key,
+                             void **result)
+{
+  gabe_cph_t* cph;
+  char* plt;
+  char* cph_buf;
+  char* aes_buf;
+  element_t m;
+  int cph_buf_len;
+  int aes_buf_len;
+  ssize_t result_len;
+
+  if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
+    return GNUNET_SYSERR;
+  cph_buf_len = gabe_cph_serialize(cph,
+                                &cph_buf);
+  gabe_cph_free(cph);
+  GNUNET_free (cph);
+  plt = GNUNET_memdup (block, size);
+  aes_buf_len = aes_128_cbc_encrypt(plt, size, m, &aes_buf);
+  GNUNET_free (plt);
+  element_clear(m);
+  result_len = write_cpabe(result, size, cph_buf, cph_buf_len, aes_buf, 
aes_buf_len);
+  GNUNET_free(cph_buf);
+  GNUNET_free(aes_buf);
+  return result_len;
+}
+
+/**
+ * @ingroup abe
+ * Decrypt a block using the ABE key.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param key the key used to decrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_decrypt (const void *block,
+                             size_t size,
+                             const struct GNUNET_ABE_AbeKey *key,
+                             void **result)
+{
+  char* aes_buf;
+  char* cph_buf;
+  gabe_cph_t* cph;
+  element_t m;
+  int cph_buf_size;
+  int aes_buf_size;
+  int plt_len;
+
+  read_cpabe(block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
+  cph = gabe_cph_unserialize(key->pub, cph_buf, cph_buf_size);
+  if( !gabe_dec(key->pub, key->prv, cph, m) ) {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "%s\n", gabe_error());
+    GNUNET_free (aes_buf);
+    GNUNET_free (cph_buf);
+    gabe_cph_free(cph);
+    GNUNET_free (cph);
+    element_clear (m);
+    return GNUNET_SYSERR;
+  }
+  gabe_cph_free(cph);
+  GNUNET_free (cph);
+  plt_len = aes_128_cbc_decrypt(aes_buf, aes_buf_size, m, (char**)result);
+  GNUNET_free (cph_buf);
+  GNUNET_free (aes_buf);
+  element_clear (m);
+  //freeing is buggy in gabe
+  //gabe_prv_free (prv);
+  //gabe_pub_free (pub);
+  return plt_len;
+}
+
+/**
+ * @ingroup abe
+ * Serialize an ABE key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
+                                   void **result)
+{
+  ssize_t len;
+  char *pub;
+  char *prv;
+  int pub_len;
+  int prv_len;
+
+  pub_len = gabe_pub_serialize (key->pub, &pub);
+  prv_len = gabe_prv_serialize (key->prv, &prv);
+
+  len = pub_len + prv_len + 12;
+  write_cpabe (result, len, pub, pub_len, prv, prv_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (prv);
+
+  return len;
+}
+
+/**
+ * @ingroup abe
+ * Deserialize a serialized ABE key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeKey*
+GNUNET_ABE_cpabe_deserialize_key (const void *data,
+                                     size_t len)
+{
+  struct GNUNET_ABE_AbeKey *key;
+  char *pub;
+  char *prv;
+  int prv_len;
+  int pub_len;
+
+  key = GNUNET_new (struct GNUNET_ABE_AbeKey);
+  read_cpabe (data,
+              &pub,
+              &pub_len,
+              &prv,
+              &prv_len);
+  key->pub = gabe_pub_unserialize (pub, pub_len);
+  key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
+  
+  GNUNET_free (pub);
+  GNUNET_free (prv);
+  return key;
+}
+
+/**
+ * @ingroup abe
+ * Serialize an ABE master key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey 
*key,
+                                          void **result)
+{
+  ssize_t len;
+  char *pub;
+  char *msk;
+  int pub_len;
+  int msk_len;
+
+  pub_len = gabe_pub_serialize (key->pub, &pub);
+  msk_len = gabe_msk_serialize (key->msk, &msk);
+
+  len = pub_len + msk_len + 12;
+  write_cpabe (result, len, pub, pub_len, msk, msk_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (msk);
+
+  return len;
+}
+
+/**
+ * @ingroup abe
+ * Deserialize an ABE master key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeMasterKey*
+GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
+                                            size_t len)
+{
+  struct GNUNET_ABE_AbeMasterKey *key;
+  char *msk;
+  char *pub;
+  int msk_len;
+  int pub_len;
+
+  key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
+  read_cpabe (data,
+              &pub,
+              &pub_len,
+              &msk,
+              &msk_len);
+  key->pub = gabe_pub_unserialize (pub, pub_len);
+  key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
+  
+  GNUNET_free (pub);
+  GNUNET_free (msk);
+
+  return key;
+}
diff --git a/src/abe/test_cpabe.c b/src/abe/test_cpabe.c
new file mode 100644
index 000000000..9b2062b23
--- /dev/null
+++ b/src/abe/test_cpabe.c
@@ -0,0 +1,87 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2002, 2003, 2004, 2006 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+
+*/
+/**
+ * @author Martin Schanzenbach
+ * @file util/test_crypto_abe.c
+ * @brief test for ABE ciphers
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_abe_lib.h"
+
+#define TESTSTRING "Hello World!"
+
+static int
+testAbecipher ()
+{
+  struct GNUNET_ABE_AbeMasterKey *msk;
+  struct GNUNET_ABE_AbeKey *key;
+  char *result;
+  char **attrs;
+  int size;
+  char *res;
+  msk = GNUNET_ABE_cpabe_create_master_key ();
+  size = GNUNET_ABE_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
+                                      "testattr", //Policy
+                                      msk,
+                                      (void*)&result);
+  GNUNET_assert (-1 != size);
+  attrs = GNUNET_malloc (2 * sizeof (char*));
+  attrs[0] = "testattr";
+  attrs[1] = NULL;
+  key = GNUNET_ABE_cpabe_create_key (msk,
+                                        attrs);
+
+  size = GNUNET_ABE_cpabe_decrypt (result, size,
+                                      key,
+                                      (void*)&res);
+  if (strlen (TESTSTRING) + 1 != size)
+  {
+    printf ("abeciphertest failed: decryptBlock returned %d\n", size);
+    return 1;
+  }
+  if (0 != strcmp (res, TESTSTRING))
+  {
+    printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING);
+    return 1;
+  }
+  else
+    return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int failureCount = 0;
+
+  GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL);
+  failureCount += testAbecipher ();
+
+  if (failureCount != 0)
+  {
+    printf ("%d TESTS FAILED!\n", failureCount);
+    return -1;
+  }
+  return 0;
+}
+
+/* end of test_crypto_aes.c */
diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
new file mode 100644
index 000000000..ca11c5e4f
--- /dev/null
+++ b/src/credential/Makefile.am
@@ -0,0 +1,112 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+EXTRA_DIST = \
+  test_credential_defaults.conf \
+  test_credential_lookup.conf
+
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+endif
+
+pkgcfgdir = $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+plugindir = $(libdir)/gnunet
+
+pkgcfg_DATA = \
+  credential.conf
+
+
+# /usr/lib - compiles a layer which can be used to be communicagte with the 
service
+lib_LTLIBRARIES = \
+  libgnunetcredential.la
+
+# /usr/lib/gnunet/libexec - Business logic . Separate process 
+libexec_PROGRAMS = \
+  gnunet-service-credential 
+
+bin_PROGRAMS = \
+  gnunet-credential
+
+plugin_LTLIBRARIES = \
+  libgnunet_plugin_gnsrecord_credential.la
+
+
+if HAVE_MHD
+if HAVE_JSON
+plugin_LTLIBRARIES += libgnunet_plugin_rest_credential.la
+endif
+endif
+
+
+gnunet_credential_SOURCES = \
+ gnunet-credential.c
+gnunet_credential_LDADD = \
+  libgnunetcredential.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+       $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+  $(top_builddir)/src/identity/libgnunetidentity.la \
+  $(GN_LIBINTL)
+
+
+libgnunet_plugin_gnsrecord_credential_la_SOURCES = \
+  plugin_gnsrecord_credential.c
+libgnunet_plugin_gnsrecord_credential_la_LIBADD = \
+       libgnunetcredential.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunet_plugin_gnsrecord_credential_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+
+gnunet_service_credential_SOURCES = \
+ gnunet-service-credential.c
+gnunet_service_credential_LDADD = \
+       libgnunetcredential.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+       $(top_builddir)/src/gns/libgnunetgns.la \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(GN_LIBINTL)
+
+
+libgnunetcredential_la_SOURCES = \
+ credential_api.c \
+ credential_serialization.c \
+ credential_misc.c
+libgnunetcredential_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) 
+libgnunetcredential_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS)
+
+
+libgnunet_plugin_rest_credential_la_SOURCES = \
+  plugin_rest_credential.c
+libgnunet_plugin_rest_credential_la_LIBADD = \
+  libgnunetcredential.la \
+       $(top_builddir)/src/rest/libgnunetrest.la \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+  $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_credential_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+check_SCRIPTS = \
+  test_credential_issue.sh \
+       test_credential_verify_simple.sh \
+       test_credential_verify.sh \
+       test_credential_verify_and.sh
+
+if ENABLE_TEST_RUN
+if HAVE_SQLITE
+ AM_TESTS_ENVIRONMENT=export 
GNUNET_PREFIX=$${GNUNET_PREFIX:address@hidden@};export 
PATH=$${GNUNET_PREFIX:address@hidden@}/bin:$$PATH;
+ TESTS = $(check_SCRIPTS)
+endif
+endif
diff --git a/src/credential/credential.conf.in 
b/src/credential/credential.conf.in
new file mode 100644
index 000000000..71f3066ca
--- /dev/null
+++ b/src/credential/credential.conf.in
@@ -0,0 +1,5 @@
+[credential]
+BINARY = gnunet-service-credential
+UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-credential.sock
+USER_SERVICE = YES
+OPTIONS = -L DEBUG
\ No newline at end of file
diff --git a/src/credential/credential.h b/src/credential/credential.h
new file mode 100644
index 000000000..66a4636fc
--- /dev/null
+++ b/src/credential/credential.h
@@ -0,0 +1,221 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2012-2013 GNUnet e.V.
+
+      GNUnet is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published
+      by the Free Software Foundation; either version 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+      Boston, MA 02110-1301, USA.
+ */
+/**
+ * @file credential/credential.h
+ * @brief IPC messages between CREDENTIAL API and CREDENTIAL service
+ * @author Martin Schanzenbach
+ */
+#ifndef CREDENTIAL_H
+#define CREDENTIAL_H
+
+#include "gnunet_credential_service.h"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message from client to Credential service to collect credentials.
+ */
+struct CollectMessage
+{
+  /**
+   * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Subject public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key;
+
+  /**
+   * Trust anchor
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * Length of the issuer attribute
+   */
+  uint16_t issuer_attribute_len;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /* Followed by the zero-terminated attribute */
+
+};
+
+
+/**
+ * Message from client to Credential service to verify attributes.
+ */
+struct VerifyMessage
+{
+  /**
+   * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Subject public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  /**
+   * Trust anchor
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * Number of credentials
+   */
+  uint32_t c_count;
+
+  /**
+   * Length of the issuer attribute
+   */
+  uint16_t issuer_attribute_len;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /* Followed by the zero-terminated attribute and credentials to look up */
+
+};
+
+
+/**
+ * Message from CREDENTIAL service to client: new results.
+ */
+struct DelegationChainResultMessage
+{
+  /**
+    * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+  
+  /**
+   * Indicates if credential has been found at all
+   */
+  uint32_t cred_found GNUNET_PACKED;
+
+  /**
+   * The number of delegations in the response
+   */
+  uint32_t d_count GNUNET_PACKED;
+
+  /**
+   * The number of credentials in the response
+   */
+  uint32_t c_count GNUNET_PACKED;
+
+  /* followed by ad_count GNUNET_CREDENTIAL_RecordData structs*/
+
+};
+
+struct DelegationRecordData
+{
+  /**
+   * Subject key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+  
+  /**
+   * Subject attributes
+   */
+  uint32_t subject_attribute_len GNUNET_PACKED;
+};
+
+
+struct ChainEntry
+{
+  /**
+   * Issuer key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+  
+  /**
+   * Subject key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+  
+  /**
+   * Issuer attributes
+   */
+  uint32_t issuer_attribute_len GNUNET_PACKED;
+  
+  /**
+   * Subject attributes
+   */
+  uint32_t subject_attribute_len GNUNET_PACKED;
+};
+
+
+struct CredentialEntry
+{
+
+  /**
+   * The signature for this credential by the issuer
+   */
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+
+  /**
+   * Signature meta
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Public key of the issuer
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * Public key of the subject this credential was issued to
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  /**
+   * Expiration time of this credential
+   */
+  uint64_t expiration GNUNET_PACKED;
+   
+  /**
+   * Issuer attribute length
+   */
+  uint32_t issuer_attribute_len;
+
+  /**
+   * Followed by the attribute string
+   */
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
+
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
new file mode 100644
index 000000000..677cb9ad4
--- /dev/null
+++ b/src/credential/credential_api.c
@@ -0,0 +1,511 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file credential/credential_api.c
+ * @brief library to access the CREDENTIAL service
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_arm_service.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+#include "credential_serialization.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_identity_service.h"
+
+
+#define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
+
+/**
+ * Handle to a verify request
+ */
+struct GNUNET_CREDENTIAL_Request
+{
+
+  /**
+   * DLL
+   */
+  struct GNUNET_CREDENTIAL_Request *next;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_CREDENTIAL_Request *prev;
+
+  /**
+   * handle to credential service
+   */
+  struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
+  /**
+   * processor to call on verify result
+   */
+  GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc;
+
+  /**
+   * @e verify_proc closure
+   */
+  void *proc_cls;
+
+  /**
+   * Envelope with the message for this queue entry.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+
+};
+
+
+/**
+ * Connection to the CREDENTIAL service.
+ */
+struct GNUNET_CREDENTIAL_Handle
+{
+
+  /**
+   * Configuration to use.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Connection to service (if available).
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Head of linked list of active verify requests.
+   */
+  struct GNUNET_CREDENTIAL_Request *request_head;
+
+  /**
+   * Tail of linked list of active verify requests.
+   */
+  struct GNUNET_CREDENTIAL_Request *request_tail;
+
+  /**
+   * Reconnect task
+   */
+  struct GNUNET_SCHEDULER_Task *reconnect_task;
+
+  /**
+   * How long do we wait until we try to reconnect?
+   */
+  struct GNUNET_TIME_Relative reconnect_backoff;
+
+  /**
+   * Request Id generator.  Incremented by one for each request.
+   */
+  uint32_t r_id_gen;
+
+};
+
+
+/**
+ * Reconnect to CREDENTIAL service.
+ *
+ * @param handle the handle to the CREDENTIAL service
+ */
+static void
+reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
+
+
+/**
+ * Reconnect to CREDENTIAL
+ *
+ * @param cls the handle
+ */
+static void
+reconnect_task (void *cls)
+{
+  struct GNUNET_CREDENTIAL_Handle *handle = cls;
+
+  handle->reconnect_task = NULL;
+  reconnect (handle);
+}
+
+
+/**
+ * Disconnect from service and then reconnect.
+ *
+ * @param handle our handle
+ */
+static void
+force_reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
+{
+  GNUNET_MQ_destroy (handle->mq);
+  handle->mq = NULL;
+  handle->reconnect_backoff
+    = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
+  handle->reconnect_task
+    = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
+                        &reconnect_task,
+                        handle);
+}
+
+
+/**
+ * Generic error handler, called with the appropriate error code and
+ * the same closure specified at the creation of the message queue.
+ * Not every message queue implementation supports an error handler.
+ *
+ * @param cls closure with the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_CREDENTIAL_Handle *handle = cls;
+
+  force_reconnect (handle);
+}
+
+/**
+ * Check validity of message received from the CREDENTIAL service
+ *
+ * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param vr_msg the incoming message
+ */
+static int
+check_result (void *cls,
+              const struct DelegationChainResultMessage *vr_msg)
+{
+  //TODO
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handler for messages received from the CREDENTIAL service
+ *
+ * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
+ * @param vr_msg the incoming message
+ */
+static void
+handle_result (void *cls,
+               const struct DelegationChainResultMessage *vr_msg)
+{
+  struct GNUNET_CREDENTIAL_Handle *handle = cls;
+  uint32_t r_id = ntohl (vr_msg->id);
+  struct GNUNET_CREDENTIAL_Request *vr;
+  size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
+  uint32_t d_count = ntohl (vr_msg->d_count);
+  uint32_t c_count = ntohl (vr_msg->c_count);
+  struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
+  struct GNUNET_CREDENTIAL_Credential creds[c_count];
+  GNUNET_CREDENTIAL_CredentialResultProcessor proc;
+  void *proc_cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received verify reply from CREDENTIAL service\n");
+  for (vr = handle->request_head; NULL != vr; vr = vr->next)
+    if (vr->r_id == r_id)
+      break;
+  if (NULL == vr)
+    return;
+  proc = vr->verify_proc;
+  proc_cls = vr->proc_cls;
+  GNUNET_CONTAINER_DLL_remove (handle->request_head,
+                               handle->request_tail,
+                               vr);
+  GNUNET_MQ_discard (vr->env);
+  GNUNET_free (vr);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
+                                                                 (const char*) 
&vr_msg[1],
+                                                                 d_count,
+                                                                 d_chain,
+                                                                 c_count,
+                                                                 creds));
+  if (GNUNET_NO == ntohl (vr_msg->cred_found))
+  {
+    proc (proc_cls,
+          0,
+          NULL,
+          0,
+          NULL); // TODO
+  } else {
+    proc (proc_cls,
+          d_count,
+          d_chain,
+          c_count,
+          creds);
+  }
+}
+
+
+/**
+ * Reconnect to CREDENTIAL service.
+ *
+ * @param handle the handle to the CREDENTIAL service
+ */
+static void
+reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
+{
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_var_size (result,
+                           GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
+                           struct DelegationChainResultMessage,
+                           handle),
+    GNUNET_MQ_hd_var_size (result,
+                           GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
+                           struct DelegationChainResultMessage,
+                           handle),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_CREDENTIAL_Request *vr;
+
+  GNUNET_assert (NULL == handle->mq);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Trying to connect to CREDENTIAL\n");
+  handle->mq = GNUNET_CLIENT_connect (handle->cfg,
+                                      "credential",
+                                      handlers,
+                                      &mq_error_handler,
+                                      handle);
+  if (NULL == handle->mq)
+    return;
+  for (vr = handle->request_head; NULL != vr; vr = vr->next)
+    GNUNET_MQ_send_copy (handle->mq,
+                         vr->env);
+}
+
+
+/**
+ * Initialize the connection with the CREDENTIAL service.
+ *
+ * @param cfg configuration to use
+ * @return handle to the CREDENTIAL service, or NULL on error
+ */
+struct GNUNET_CREDENTIAL_Handle *
+GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_CREDENTIAL_Handle *handle;
+
+  handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
+  handle->cfg = cfg;
+  reconnect (handle);
+  if (NULL == handle->mq)
+  {
+    GNUNET_free (handle);
+    return NULL;
+  }
+  return handle;
+}
+
+
+/**
+ * Shutdown connection with the CREDENTIAL service.
+ *
+ * @param handle handle of the CREDENTIAL connection to stop
+ */
+void
+GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
+{
+  if (NULL != handle->mq)
+  {
+    GNUNET_MQ_destroy (handle->mq);
+    handle->mq = NULL;
+  }
+  if (NULL != handle->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle->reconnect_task);
+    handle->reconnect_task = NULL;
+  }
+  GNUNET_assert (NULL == handle->request_head);
+  GNUNET_free (handle);
+}
+
+
+/**
+ * Cancel pending verify request
+ *
+ * @param lr the verify request to cancel
+ */
+void
+GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr)
+{
+  struct GNUNET_CREDENTIAL_Handle *handle = lr->credential_handle;
+
+  GNUNET_CONTAINER_DLL_remove (handle->request_head,
+                               handle->request_tail,
+                               lr);
+  GNUNET_MQ_discard (lr->env);
+  GNUNET_free (lr);
+}
+
+
+/**
+ * Performs attribute collection.
+ * Collects all credentials of subject to fulfill the 
+ * attribute, if possible
+ *
+ * @param handle handle to the Credential service
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
+                           const char *issuer_attribute,
+                           const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*subject_key,
+                           GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+                           void *proc_cls)
+{
+  /* IPC to shorten credential names, return shorten_handle */
+  struct CollectMessage *c_msg;
+  struct GNUNET_CREDENTIAL_Request *vr;
+  size_t nlen;
+
+  if (NULL == issuer_attribute)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  //DEBUG LOG
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Trying to collect `%s' in CREDENTIAL\n",
+       issuer_attribute);
+  nlen = strlen (issuer_attribute) + 1;
+  if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
+  vr->credential_handle = handle;
+  vr->verify_proc = proc;
+  vr->proc_cls = proc_cls;
+  vr->r_id = handle->r_id_gen++;
+  vr->env = GNUNET_MQ_msg_extra (c_msg,
+                                 nlen,
+                                 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
+  c_msg->id = htonl (vr->r_id);
+  c_msg->subject_key = *subject_key;
+  c_msg->issuer_key =  *issuer_key;
+  c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
+  GNUNET_memcpy (&c_msg[1],
+                 issuer_attribute,
+                 strlen (issuer_attribute));
+  GNUNET_CONTAINER_DLL_insert (handle->request_head,
+                               handle->request_tail,
+                               vr);
+  if (NULL != handle->mq)
+    GNUNET_MQ_send_copy (handle->mq,
+                         vr->env);
+  return vr;
+}
+/**
+ * Performs attribute verification.
+ * Checks if there is a delegation chain from
+ * attribute ``issuer_attribute'' issued by the issuer
+ * with public key ``issuer_key'' maps to the attribute
+ * ``subject_attribute'' claimed by the subject with key
+ * ``subject_key''
+ *
+ * @param handle handle to the Credential service
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param credential_count number of credentials provided
+ * @param credentials subject credentials
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
+                          const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
+                          const char *issuer_attribute,
+                          const struct GNUNET_CRYPTO_EcdsaPublicKey 
*subject_key,
+                          uint32_t credential_count,
+                          const struct GNUNET_CREDENTIAL_Credential 
*credentials,
+                          GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+                          void *proc_cls)
+{
+  /* IPC to shorten credential names, return shorten_handle */
+  struct VerifyMessage *v_msg;
+  struct GNUNET_CREDENTIAL_Request *vr;
+  size_t nlen;
+  size_t clen;
+
+  if (NULL == issuer_attribute || NULL == credentials)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
+                                                 credentials);
+
+  //DEBUG LOG
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Trying to verify `%s' in CREDENTIAL\n",
+       issuer_attribute);
+  nlen = strlen (issuer_attribute) + 1 + clen;
+  if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
+  vr->credential_handle = handle;
+  vr->verify_proc = proc;
+  vr->proc_cls = proc_cls;
+  vr->r_id = handle->r_id_gen++;
+  vr->env = GNUNET_MQ_msg_extra (v_msg,
+                                 nlen,
+                                 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
+  v_msg->id = htonl (vr->r_id);
+  v_msg->subject_key = *subject_key;
+  v_msg->c_count = htonl(credential_count);
+  v_msg->issuer_key =  *issuer_key;
+  v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
+  GNUNET_memcpy (&v_msg[1],
+                 issuer_attribute,
+                 strlen (issuer_attribute));
+  GNUNET_CREDENTIAL_credentials_serialize (credential_count,
+                                           credentials,
+                                           clen,
+                                           ((char*)&v_msg[1])
+                                           + strlen (issuer_attribute) + 1);
+  GNUNET_CONTAINER_DLL_insert (handle->request_head,
+                               handle->request_tail,
+                               vr);
+  if (NULL != handle->mq)
+    GNUNET_MQ_send_copy (handle->mq,
+                         vr->env);
+  return vr;
+}
+
+/* end of credential_api.c */
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c
new file mode 100644
index 000000000..c94c33919
--- /dev/null
+++ b/src/credential/credential_misc.c
@@ -0,0 +1,168 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_misc.c
+ * @brief Misc API for credentials
+ *
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+#include <inttypes.h>
+
+char*
+GNUNET_CREDENTIAL_credential_to_string (const struct 
GNUNET_CREDENTIAL_Credential *cred)
+{
+  char *cred_str;
+  char *subject_pkey;
+  char *issuer_pkey;
+  char *signature;
+
+
+  subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+  issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+  GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
+                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+                                &signature);
+  GNUNET_asprintf (&cred_str,
+                   "%s.%s -> %s | %s | %"SCNu64,
+                   issuer_pkey,
+                   cred->issuer_attribute,
+                   subject_pkey,
+                   signature,
+                   cred->expiration.abs_value_us);
+  GNUNET_free (subject_pkey);
+  GNUNET_free (issuer_pkey);
+  GNUNET_free (signature);
+  return cred_str;
+}
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_from_string (const char* s)
+{
+  struct GNUNET_CREDENTIAL_Credential *cred;
+  size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
+  if (enclen % 5 > 0)
+    enclen += 5 - enclen % 5;
+  enclen /= 5; /* 260/5 = 52 */
+  char subject_pkey[enclen + 1];
+  char issuer_pkey[enclen + 1];
+  char name[253 + 1];
+  char signature[256]; //TODO max payload size
+
+  struct GNUNET_CRYPTO_EcdsaSignature *sig;
+  struct GNUNET_TIME_Absolute etime_abs;
+
+  if (5 != SSCANF (s,
+                   "%52s.%253s -> %52s | %s | %"SCNu64,
+                   issuer_pkey,
+                   name,
+                   subject_pkey,
+                   signature,
+                   &etime_abs.abs_value_us))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Unable to parse CRED record string `%s'\n"),
+                s);
+    return NULL;
+  }
+  cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen 
(name) + 1);
+  GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
+                                              strlen (subject_pkey),
+                                              &cred->subject_key);
+  GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
+                                              strlen (issuer_pkey),
+                                              &cred->issuer_key);
+  GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == 
GNUNET_STRINGS_base64_decode (signature,
+                                strlen (signature),
+                                (char**)&sig));
+  cred->signature = *sig;
+  cred->expiration = etime_abs;
+  GNUNET_free (sig);
+  GNUNET_memcpy (&cred[1],
+                 name,
+                 strlen (name)+1);
+  cred->issuer_attribute_len = strlen ((char*)&cred[1]);
+  cred->issuer_attribute = (char*)&cred[1];
+  return cred;
+}
+
+/**
+ * Issue an attribute to a subject
+ *
+ * @param issuer the ego that should be used to issue the attribute
+ * @param subject the subject of the attribute
+ * @param attribute the name of the attribute
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Credential *
+GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*issuer,
+                                    struct GNUNET_CRYPTO_EcdsaPublicKey 
*subject,
+                                    const char *attribute,
+                                    struct GNUNET_TIME_Absolute *expiration)
+{
+  struct CredentialEntry *crd;
+  struct GNUNET_CREDENTIAL_Credential *cred;
+  size_t size;
+
+  size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
+  crd = GNUNET_malloc (size);
+  cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen 
(attribute) + 1);
+  crd->purpose.size = htonl (size - sizeof (struct 
GNUNET_CRYPTO_EcdsaSignature));
+
+  crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+  GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
+                                      &crd->issuer_key);
+  crd->subject_key = *subject;
+  crd->expiration = GNUNET_htonll (expiration->abs_value_us);
+  crd->issuer_attribute_len = htonl (strlen (attribute)+1);
+  GNUNET_memcpy ((char*)&crd[1],
+                 attribute,
+                 strlen (attribute)+1);
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdsa_sign (issuer,
+                                &crd->purpose,
+                                &crd->signature))
+  {
+    GNUNET_break (0);
+    GNUNET_free (crd);
+    return NULL;
+  }
+  cred->signature = crd->signature;
+  cred->expiration = *expiration;
+  GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
+                                      &cred->issuer_key);
+
+  cred->subject_key = *subject;
+  GNUNET_memcpy (&cred[1],
+                 attribute,
+                 strlen (attribute)+1);
+  cred->issuer_attribute = (char*)&cred[1];
+  GNUNET_free (crd);
+  return cred;
+}
+
+
diff --git a/src/include/gnunet_sensordashboard_service.h 
b/src/credential/credential_misc.h
similarity index 59%
copy from src/include/gnunet_sensordashboard_service.h
copy to src/credential/credential_misc.h
index bd4acb271..c3aa8c214 100644
--- a/src/include/gnunet_sensordashboard_service.h
+++ b/src/credential/credential_misc.h
@@ -1,6 +1,6 @@
 /*
       This file is part of GNUnet
-      Copyright (C)
+      Copyright (C) 2012-2013 GNUnet e.V.
 
       GNUnet is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
@@ -17,39 +17,19 @@
       Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       Boston, MA 02110-1301, USA.
  */
-
 /**
- * @author Omar Tarabai
- *
- * @file
- * API to the sensordashboard service
- *
- * @defgroup sensordashboard  Sensor Dashboard service
- *
- * @{
+ * @file credential/credential_misc.h
+ * @brief Credential helper functions
  */
-#ifndef GNUNET_SENSORDASHBOARD_SERVICE_H
-#define GNUNET_SENSORDASHBOARD_SERVICE_H
+#ifndef CREDENTIAL_MISC_H
+#define CREDENTIAL_MISC_H
 
-#include "gnunet_common.h"
-#include "gnunet_util_lib.h"
 
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
 
+char*
+GNUNET_CREDENTIAL_credential_to_string (const struct 
GNUNET_CREDENTIAL_Credential *cred);
 
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_from_string (const char* str);
 
 #endif
-
-/** @} */  /* end of group */
diff --git a/src/credential/credential_serialization.c 
b/src/credential/credential_serialization.c
new file mode 100644
index 000000000..1d23bb08c
--- /dev/null
+++ b/src/credential/credential_serialization.c
@@ -0,0 +1,460 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_serialization.c
+ * @brief API to serialize and deserialize delegation chains 
+ * and credentials
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain
+ *
+ * @param ds_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
+                                           const struct 
GNUNET_CREDENTIAL_DelegationSet *dsr)
+{
+  unsigned int i;
+  size_t ret;
+
+  ret = sizeof (struct DelegationRecordData) * (ds_count);
+
+  for (i=0; i<ds_count;i++)
+  {
+    GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
+    ret += dsr[i].subject_attribute_len;
+  }
+  return ret;
+}
+
+/**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
+                                            const struct 
GNUNET_CREDENTIAL_DelegationSet *dsr,
+                                            size_t dest_size,
+                                            char *dest)
+{
+  struct DelegationRecordData rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<d_count;i++)
+  {
+    rec.subject_attribute_len = htonl ((uint32_t) 
dsr[i].subject_attribute_len);
+    rec.subject_key = dsr[i].subject_key;
+    if (off + sizeof (rec) > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   &rec,
+                   sizeof (rec));
+    off += sizeof (rec);
+    if (0 == dsr[i].subject_attribute_len)
+      continue;
+    if (off + dsr[i].subject_attribute_len > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   dsr[i].subject_attribute,
+                   dsr[i].subject_attribute_len);
+    off += dsr[i].subject_attribute_len;
+  }
+  return off;
+}
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation chain and cred
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dsr where to put the delegation chain entries
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
+                                              const char *src,
+                                              unsigned int d_count,
+                                              struct 
GNUNET_CREDENTIAL_DelegationSet *dsr)
+{
+  struct DelegationRecordData rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<d_count;i++)
+  {
+    if (off + sizeof (rec) > len)
+      return GNUNET_SYSERR;
+    GNUNET_memcpy (&rec, &src[off], sizeof (rec));
+    dsr[i].subject_key = rec.subject_key;
+    off += sizeof (rec);
+    dsr[i].subject_attribute_len = ntohl ((uint32_t) 
rec.subject_attribute_len);
+    if (off + dsr[i].subject_attribute_len > len)
+      return GNUNET_SYSERR;
+    dsr[i].subject_attribute = (char*)&src[off];
+    off += dsr[i].subject_attribute_len;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+                                        const struct 
GNUNET_CREDENTIAL_Credential *cd)
+{
+  unsigned int i;
+  size_t ret;
+
+  ret = sizeof (struct CredentialEntry) * (c_count);
+
+  for (i=0; i<c_count;i++)
+  {
+    GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
+    ret += cd[i].issuer_attribute_len;
+  }
+  return ret;
+}
+/**
+ * Serizalize the given credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+                                         const struct 
GNUNET_CREDENTIAL_Credential *cd,
+                                         size_t dest_size,
+                                         char *dest)
+{
+  struct CredentialEntry c_rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<c_count;i++)
+  {
+    c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
+    c_rec.issuer_key = cd[i].issuer_key;
+    c_rec.subject_key = cd[i].subject_key;
+    c_rec.signature = cd[i].signature;
+    c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+    c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + 
cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+    c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
+    if (off + sizeof (c_rec) > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   &c_rec,
+                   sizeof (c_rec));
+    off += sizeof (c_rec);
+    if (off + cd[i].issuer_attribute_len > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   cd[i].issuer_attribute,
+                   cd[i].issuer_attribute_len);
+    off += cd[i].issuer_attribute_len;
+  }
+
+  return off;
+}
+
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized creds
+ * @param src the serialized data
+ * @param c_count the number of credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+                                           const char *src,
+                                           unsigned int c_count,
+                                           struct GNUNET_CREDENTIAL_Credential 
*cd)
+{
+  struct CredentialEntry c_rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<c_count;i++)
+  {
+    if (off + sizeof (c_rec) > len)
+      return GNUNET_SYSERR;
+    GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
+    cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
+    cd[i].issuer_key = c_rec.issuer_key;
+    cd[i].subject_key = c_rec.subject_key;
+    cd[i].signature = c_rec.signature;
+    cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
+    off += sizeof (c_rec);
+    if (off + cd[i].issuer_attribute_len > len)
+      return GNUNET_SYSERR;
+    cd[i].issuer_attribute = &src[off];
+    off += cd[i].issuer_attribute_len;
+  }
+  return GNUNET_OK;
+}
+
+
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
+                                             const struct 
GNUNET_CREDENTIAL_Delegation *dd,
+                                             unsigned int c_count,
+                                             const struct 
GNUNET_CREDENTIAL_Credential *cd)
+{
+  unsigned int i;
+  size_t ret;
+
+  ret = sizeof (struct ChainEntry) * (d_count);
+
+  for (i=0; i<d_count;i++)
+  {
+    GNUNET_assert ((ret +
+                    dd[i].issuer_attribute_len +
+                    dd[i].subject_attribute_len) >= ret);
+    ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
+  }
+  return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
+  return ret;
+}
+
+/**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
+                                              const struct 
GNUNET_CREDENTIAL_Delegation *dd,
+                                              unsigned int c_count,
+                                              const struct 
GNUNET_CREDENTIAL_Credential *cd,
+                                              size_t dest_size,
+                                              char *dest)
+{
+  struct ChainEntry rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<d_count;i++)
+  {
+    rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
+    rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
+    rec.issuer_key = dd[i].issuer_key;
+    rec.subject_key = dd[i].subject_key;
+    if (off + sizeof (rec) > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   &rec,
+                   sizeof (rec));
+    off += sizeof (rec);
+    if (off + dd[i].issuer_attribute_len > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   dd[i].issuer_attribute,
+                   dd[i].issuer_attribute_len);
+    off += dd[i].issuer_attribute_len;
+    if (0 == dd[i].subject_attribute_len)
+      continue;
+    if (off + dd[i].subject_attribute_len > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   dd[i].subject_attribute,
+                   dd[i].subject_attribute_len);
+    off += dd[i].subject_attribute_len;
+  }
+  return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
+                                                      cd,
+                                                      dest_size-off,
+                                                      &dest[off]);
+}
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation chain and cred
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dd where to put the delegation chain entries
+ * @param c_count the number of credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
+                                                const char *src,
+                                                unsigned int d_count,
+                                                struct 
GNUNET_CREDENTIAL_Delegation *dd,
+                                                unsigned int c_count,
+                                                struct 
GNUNET_CREDENTIAL_Credential *cd)
+{
+  struct ChainEntry rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<d_count;i++)
+  {
+    if (off + sizeof (rec) > len)
+      return GNUNET_SYSERR;
+    GNUNET_memcpy (&rec, &src[off], sizeof (rec));
+    dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
+    dd[i].issuer_key = rec.issuer_key;
+    dd[i].subject_key = rec.subject_key;
+    off += sizeof (rec);
+    if (off + dd[i].issuer_attribute_len > len)
+      return GNUNET_SYSERR;
+    dd[i].issuer_attribute = &src[off];
+    off += dd[i].issuer_attribute_len;
+    dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
+    if (off + dd[i].subject_attribute_len > len)
+      return GNUNET_SYSERR;
+    dd[i].subject_attribute = &src[off];
+    off += dd[i].subject_attribute_len;
+  }
+  return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
+                                                    &src[off],
+                                                    c_count,
+                                                    cd);
+}
+int
+GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential 
*cred,
+                                        char **data)
+{
+  size_t size;
+  struct CredentialEntry *cdata;
+
+  size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
+  *data = GNUNET_malloc (size);
+  cdata = (struct CredentialEntry*)*data;
+  cdata->subject_key = cred->subject_key;
+  cdata->issuer_key = cred->issuer_key;
+  cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
+  cdata->signature = cred->signature;
+  cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
+  cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+  cdata->purpose.size = htonl (size - sizeof (struct 
GNUNET_CRYPTO_EcdsaSignature));
+  GNUNET_memcpy (&cdata[1],
+                 cred->issuer_attribute,
+                 strlen (cred->issuer_attribute));
+
+  if(GNUNET_OK != 
GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, 
+                                             &cdata->purpose,
+                                             &cdata->signature,
+                                             &cdata->issuer_key))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid credential\n");
+    //return NULL;
+  }
+  return size;
+}
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_deserialize (const char* data,
+                                          size_t data_size)
+{
+  struct GNUNET_CREDENTIAL_Credential *cred;
+  struct CredentialEntry *cdata;
+  char *issuer_attribute;
+
+  if (data_size < sizeof (struct CredentialEntry))
+    return NULL;
+  cdata = (struct CredentialEntry*)data;
+  if(GNUNET_OK != 
GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, 
+                                             &cdata->purpose,
+                                             &cdata->signature,
+                                             &cdata->issuer_key))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid credential\n");
+    //return NULL;
+  }
+  issuer_attribute = (char*)&cdata[1];
+
+  cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + 
ntohl(cdata->issuer_attribute_len));
+
+  cred->issuer_key = cdata->issuer_key;
+  cred->subject_key = cdata->subject_key;
+  GNUNET_memcpy (&cred[1],
+                 issuer_attribute,
+                 ntohl (cdata->issuer_attribute_len));
+  cred->signature = cdata->signature;
+  cred->issuer_attribute = (char*)&cred[1];
+  cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
+  return cred;
+}
+
+
+/* end of credential_serialization.c */
diff --git a/src/credential/credential_serialization.h 
b/src/credential/credential_serialization.h
new file mode 100644
index 000000000..b870d47dc
--- /dev/null
+++ b/src/credential/credential_serialization.h
@@ -0,0 +1,159 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2013, 2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+
+/**
+ * @file credential/credential_serialization.h
+ * @brief API to serialize and deserialize delegation chains 
+ * and credentials
+ * @author Martin Schanzenbach
+ */
+#ifndef CREDENTIAL_SERIALIZATION_H
+#define CREDENTIAL_SERIALIZATION_H
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_credential_service.h"
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation record
+ *
+ * @param ds_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_Delegation
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
+                                           const struct 
GNUNET_CREDENTIAL_DelegationSet *dsr);
+
+/**
+ * Serizalize the given delegation record entries
+ *
+ * @param d_count number of delegation chain entries
+ * @param dsr array of #GNUNET_CREDENTIAL_Delegation
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
+                                            const struct 
GNUNET_CREDENTIAL_DelegationSet *dsr,
+                                            size_t dest_size,
+                                            char *dest);
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation recird
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dsr where to put the delegation chain entries
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
+                                              const char *src,
+                                              unsigned int d_count,
+                                              struct 
GNUNET_CREDENTIAL_DelegationSet *dsr);
+
+  /**
+   * Calculate how many bytes we will need to serialize
+   * the given delegation chain and credential
+   *
+   * @param d_count number of delegation chain entries
+   * @param dd array of #GNUNET_CREDENTIAL_Delegation
+   * @param c_count number of credential entries
+   * @param cd a #GNUNET_CREDENTIAL_Credential
+   * @return the required size to serialize
+   */
+  size_t
+    GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
+                                                 const struct 
GNUNET_CREDENTIAL_Delegation *dd,
+                                                 unsigned int c_count,
+                                                 const struct 
GNUNET_CREDENTIAL_Credential *cd);
+
+  /**
+   * Serizalize the given delegation chain entries and credential
+   *
+   * @param d_count number of delegation chain entries
+   * @param dd array of #GNUNET_CREDENTIAL_Delegation
+   * @param c_count number of credential entries
+   * @param cd a #GNUNET_CREDENTIAL_Credential
+   * @param dest_size size of the destination
+   * @param dest where to store the result
+   * @return the size of the data, -1 on failure
+   */
+  ssize_t
+    GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
+                                                  const struct 
GNUNET_CREDENTIAL_Delegation *dd,
+                                                  unsigned int c_count,
+                                                  const struct 
GNUNET_CREDENTIAL_Credential *cd,
+                                                  size_t dest_size,
+                                                  char *dest);
+
+
+  /**
+   * Deserialize the given destination
+   *
+   * @param len size of the serialized delegation chain and cred
+   * @param src the serialized data
+   * @param d_count the number of delegation chain entries
+   * @param dd where to put the delegation chain entries
+   * @param c_count number of credential entries
+   * @param cd where to put the credential data
+   * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+   */
+  int
+    GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
+                                                    const char *src,
+                                                    unsigned int d_count,
+                                                    struct 
GNUNET_CREDENTIAL_Delegation *dd,
+                                                    unsigned int c_count,
+                                                    struct 
GNUNET_CREDENTIAL_Credential *cd);
+  size_t
+  GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+                                          const struct 
GNUNET_CREDENTIAL_Credential *cd);
+
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+                                         const struct 
GNUNET_CREDENTIAL_Credential *cd,
+                                         size_t dest_size,
+                                         char *dest);
+
+
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+                                           const char *src,
+                                           unsigned int c_count,
+                                           struct GNUNET_CREDENTIAL_Credential 
*cd);
+
+
+int
+GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential 
*cred,
+                                        char **data);
+
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_deserialize (const char* data,
+                                          size_t data_size);
+#endif
+/* end of credential_serialization.h */
diff --git a/src/credential/gnunet-credential.c 
b/src/credential/gnunet-credential.c
new file mode 100644
index 000000000..03f959b95
--- /dev/null
+++ b/src/credential/gnunet-credential.c
@@ -0,0 +1,588 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2013 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file gnunet-credential.c
+ * @brief command line tool to access command line Credential service
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <gnunet_credential_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include "credential_misc.h"
+#include "credential_serialization.h"
+
+/**
+ * Configuration we are using.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * EgoLookup
+ */
+static struct GNUNET_IDENTITY_EgoLookup *el;
+
+/**
+ * Handle to Credential service.
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential;
+
+/**
+ * Desired timeout for the lookup (default is no timeout).
+ */
+static struct GNUNET_TIME_Relative timeout;
+
+/**
+ * Handle to verify request
+ */
+static struct GNUNET_CREDENTIAL_Request *verify_request;
+
+/**
+ * Handle to collect request
+ */
+static struct GNUNET_CREDENTIAL_Request *collect_request;
+
+/**
+ * Task scheduled to handle timeout.
+ */
+static struct GNUNET_SCHEDULER_Task *tt;
+
+/**
+ * Subject pubkey string
+ */
+static char *subject_key;
+
+/**
+ * Subject credential string
+ */
+static char *subject_credential;
+
+/**
+ * Credential TTL
+ */
+static char *expiration;
+
+/**
+ * Subject key
+ */
+struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
+
+/**
+ * Issuer key
+ */
+struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
+
+
+/**
+ * Issuer pubkey string
+ */
+static char *issuer_key;
+
+/**
+ * ego
+ */
+static char *ego_name;
+
+/**
+ * Issuer attribute
+ */
+static char *issuer_attr;
+
+/**
+ * Verify mode
+ */
+static int verify;
+
+/**
+ * Issue mode
+ */
+static int create_cred;
+
+/**
+ * Collect mode
+ */
+static int collect;
+
+/**
+ * Task run on shutdown.  Cleans up everything.
+ *
+ * @param cls unused
+ */
+static void
+do_shutdown (void *cls)
+{
+  if (NULL != verify_request)
+  {
+    GNUNET_CREDENTIAL_request_cancel (verify_request);
+    verify_request = NULL;
+  }
+  if (NULL != credential)
+  {
+    GNUNET_CREDENTIAL_disconnect (credential);
+    credential = NULL;
+  }
+  if (NULL != tt)
+  {
+    GNUNET_SCHEDULER_cancel (tt);
+    tt = NULL;
+  }
+}
+
+
+/**
+ * Task run on timeout. Triggers shutdown.
+ *
+ * @param cls unused
+ */
+static void
+do_timeout (void *cls)
+{
+  tt = NULL;
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+static void
+handle_collect_result (void *cls,
+                      unsigned int d_count,
+                      struct GNUNET_CREDENTIAL_Delegation *dc,
+                      unsigned int c_count,
+                      struct GNUNET_CREDENTIAL_Credential *cred)
+{
+  int i;
+  char* line;
+
+  verify_request = NULL;
+  if (NULL != cred)
+  {
+    for (i=0;i<c_count;i++)
+    {
+      line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
+      printf ("%s\n",
+              line);
+      GNUNET_free (line);
+    }
+  }
+
+
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+static void
+handle_verify_result (void *cls,
+                      unsigned int d_count,
+                      struct GNUNET_CREDENTIAL_Delegation *dc,
+                      unsigned int c_count,
+                      struct GNUNET_CREDENTIAL_Credential *cred)
+{
+  int i;
+  char* iss_key;
+  char* sub_key;
+
+  verify_request = NULL;
+  if (NULL == cred)
+    printf ("Failed.\n");
+  else
+  {
+    printf("Delegation Chain:\n");
+    for (i=0;i<d_count;i++)
+    {
+      iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
+      sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
+      if (0 != dc[i].subject_attribute_len)
+      {
+        printf ("(%d) %s.%s <- %s.%s\n", i,
+                iss_key, dc[i].issuer_attribute,
+                sub_key, dc[i].subject_attribute);
+      } else {
+        printf ("(%d) %s.%s <- %s\n", i,
+                iss_key, dc[i].issuer_attribute,
+                sub_key);
+      }
+      GNUNET_free (iss_key);
+      GNUNET_free (sub_key);
+    }
+    printf("\nCredentials:\n");
+    for (i=0;i<c_count;i++)
+    {
+      iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred[i].issuer_key);
+      sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string 
(&cred[i].subject_key);
+      printf ("%s.%s <- %s\n",
+              iss_key, cred[i].issuer_attribute,
+              sub_key);
+      GNUNET_free (iss_key);
+      GNUNET_free (sub_key);
+
+    }
+    printf ("Successful.\n");
+  }
+
+
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+/**
+ * Callback invoked from identity service with ego information.
+ * An @a ego of NULL means the ego was not found.
+ *
+ * @param cls closure with the configuration
+ * @param ego an ego known to identity service, or NULL
+ */
+static void
+identity_cb (void *cls,
+             const struct GNUNET_IDENTITY_Ego *ego)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
+  struct GNUNET_CREDENTIAL_Credential *crd;
+  struct GNUNET_TIME_Absolute etime_abs;
+  struct GNUNET_TIME_Relative etime_rel;
+  char *res;
+
+  el = NULL;
+  if (NULL == ego)
+  {
+    if (NULL != ego_name)
+    {
+      fprintf (stderr,
+               _("Ego `%s' not known to identity service\n"),
+               ego_name);
+    }
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_YES == collect)
+  {
+    
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
+                                                    strlen (issuer_key),
+                                                    &issuer_pkey))
+    {
+      fprintf (stderr,
+               _("Issuer public key `%s' is not well-formed\n"),
+               issuer_key);
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+
+    collect_request = GNUNET_CREDENTIAL_collect(credential,
+                                                &issuer_pkey,
+                                                issuer_attr, //TODO argument
+                                                privkey,
+                                                &handle_collect_result,
+                                                NULL);
+    return;
+  }
+
+  //Else issue
+
+  if (NULL == expiration)
+  {
+    fprintf (stderr,
+             "Please specify a TTL\n");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration,
+                                                                 &etime_rel))
+  {
+    etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
+  } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration,
+                                                                 &etime_abs))
+  {
+    fprintf (stderr,
+             "%s is not a valid ttl!\n",
+             expiration);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+
+  privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+  GNUNET_free_non_null (ego_name);
+  ego_name = NULL;
+  crd = GNUNET_CREDENTIAL_credential_issue (privkey,
+                                            &subject_pkey,
+                                            issuer_attr,
+                                            &etime_abs);
+
+  res = GNUNET_CREDENTIAL_credential_to_string (crd);
+  GNUNET_free (crd);
+  printf ("%s\n", res);
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+
+  cfg = c;
+
+
+  tt = GNUNET_SCHEDULER_add_delayed (timeout,
+                                     &do_timeout, NULL);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
+
+  if (GNUNET_YES == collect) {
+    if (NULL == issuer_key)
+    {
+      fprintf (stderr,
+               _("Issuer public key not well-formed\n"));
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+
+    }
+
+    credential = GNUNET_CREDENTIAL_connect (cfg);
+
+    if (NULL == credential)
+    {
+      fprintf (stderr,
+               _("Failed to connect to CREDENTIAL\n"));
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    if (NULL == issuer_attr)
+    {
+      fprintf (stderr,
+               _("You must provide issuer the attribute\n"));
+      GNUNET_SCHEDULER_shutdown ();
+    }
+
+    if (NULL == ego_name)
+    {
+      fprintf (stderr,
+               _("ego required\n"));
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+
+    }
+    el = GNUNET_IDENTITY_ego_lookup (cfg,
+                                     ego_name,
+                                     &identity_cb,
+                                     (void *) cfg);
+    return;
+
+  } 
+
+  if (NULL == subject_key)
+  {
+    fprintf (stderr,
+             _("Subject public key needed\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+
+  }
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_key,
+                                                  strlen (subject_key),
+                                                  &subject_pkey))
+  {
+    fprintf (stderr,
+             _("Subject public key `%s' is not well-formed\n"),
+             subject_key);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (GNUNET_YES == verify) {
+    if (NULL == issuer_key)
+    {
+      fprintf (stderr,
+               _("Issuer public key not well-formed\n"));
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+
+    }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
+                                                    strlen (issuer_key),
+                                                    &issuer_pkey))
+    {
+      fprintf (stderr,
+               _("Issuer public key `%s' is not well-formed\n"),
+               issuer_key);
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    credential = GNUNET_CREDENTIAL_connect (cfg);
+
+    if (NULL == credential)
+    {
+      fprintf (stderr,
+               _("Failed to connect to CREDENTIAL\n"));
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    if (NULL == issuer_attr || NULL == subject_credential)
+    {
+      fprintf (stderr,
+               _("You must provide issuer and subject attributes\n"));
+      GNUNET_SCHEDULER_shutdown ();
+    }
+
+    //Subject credentials are comma separated
+    char *tmp = GNUNET_strdup (subject_credential);
+    char *tok = strtok (tmp, ",");
+    if (NULL == tok)
+    {
+      fprintf (stderr,
+               "Invalid subject credentials\n");
+      GNUNET_free (tmp);
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    int count = 1;
+    int i;
+    while (NULL != (tok = strtok(NULL, ",")))
+      count++;
+    struct GNUNET_CREDENTIAL_Credential credentials[count];
+    struct GNUNET_CREDENTIAL_Credential *cred;
+    GNUNET_free (tmp);
+    tmp = GNUNET_strdup (subject_credential);
+    tok = strtok (tmp, ",");
+    for (i=0;i<count;i++)
+    {
+      cred = GNUNET_CREDENTIAL_credential_from_string (tok);
+      GNUNET_memcpy (&credentials[i],
+                     cred,
+                     sizeof (struct GNUNET_CREDENTIAL_Credential));
+      credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
+      tok = strtok(NULL, ",");
+      GNUNET_free (cred);
+    }
+
+    verify_request = GNUNET_CREDENTIAL_verify(credential,
+                                              &issuer_pkey,
+                                              issuer_attr, //TODO argument
+                                              &subject_pkey,
+                                              count,
+                                              credentials,
+                                              &handle_verify_result,
+                                              NULL);
+    for (i=0;i<count;i++)
+    {
+      GNUNET_free ((char*)credentials[i].issuer_attribute);
+    }
+  } else if (GNUNET_YES == create_cred) {
+    if (NULL == ego_name)
+    {
+      fprintf (stderr,
+               _("Issuer ego required\n"));
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+
+    }
+    el = GNUNET_IDENTITY_ego_lookup (cfg,
+                                     ego_name,
+                                     &identity_cb,
+                                     (void *) cfg);
+    return;
+  } else {
+    fprintf (stderr,
+             _("Please specify name to lookup, subject key and issuer 
key!\n"));
+    GNUNET_SCHEDULER_shutdown ();
+  }
+  return;
+}
+
+
+/**
+ * The main function for gnunet-gns.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_flag ('I',
+                               "issue",
+                               gettext_noop ("create credential"),
+                               &create_cred),
+    GNUNET_GETOPT_option_flag ('V',
+                               "verify",
+                               gettext_noop ("verify credential against 
attribute"),
+                               &verify),
+    GNUNET_GETOPT_option_string ('s',
+                                 "subject",
+                                 "PKEY",
+                                 gettext_noop ("The public key of the subject 
to lookup the credential for"),
+                                 &subject_key),
+    GNUNET_GETOPT_option_string ('b',
+                                 "credential",
+                                 "CRED",
+                                 gettext_noop ("The name of the credential 
presented by the subject"),
+                                 &subject_credential),
+    GNUNET_GETOPT_option_string ('i',
+                                 "issuer",
+                                 "PKEY",
+                                 gettext_noop ("The public key of the 
authority to verify the credential against"),
+                                 &issuer_key),
+    GNUNET_GETOPT_option_string ('e',
+                                 "ego",
+                                 "EGO",
+                                 gettext_noop ("The ego to use"),
+                                 &ego_name),
+    GNUNET_GETOPT_option_string ('a',
+                                 "attribute",
+                                 "ATTR",
+                                 gettext_noop ("The issuer attribute to verify 
against or to issue"),
+                                 &issuer_attr),
+    GNUNET_GETOPT_option_string ('T',
+                                 "ttl",
+                                 "EXP",
+                                 gettext_noop ("The time to live for the 
credential"),
+                                 &expiration),
+    GNUNET_GETOPT_option_flag ('g',
+                               "collect",
+                               gettext_noop ("collect credentials"),
+                               &collect),
+    GNUNET_GETOPT_OPTION_END
+  };
+  int ret;
+
+  timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+
+  GNUNET_log_setup ("gnunet-credential", "WARNING", NULL);
+  ret =
+    (GNUNET_OK ==
+     GNUNET_PROGRAM_run (argc, argv, "gnunet-credential",
+                         _("GNUnet credential resolver tool"),
+                         options,
+                         &run, NULL)) ? 0 : 1;
+  GNUNET_free ((void*) argv);
+  return ret;
+}
+
+/* end of gnunet-credential.c */
diff --git a/src/credential/gnunet-service-credential.c 
b/src/credential/gnunet-service-credential.c
new file mode 100644
index 000000000..be88839e9
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,1160 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011-2013 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file credential/gnunet-service-credential.c
+ * @brief GNUnet Credential Service (main service)
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_statistics_service.h"
+#include "credential.h"
+#include "credential_serialization.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+
+#include <gnunet_dnsparser_lib.h>
+#include <gnunet_identity_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_gns_service.h>
+
+
+#define GNUNET_CREDENTIAL_MAX_LENGTH 255
+
+struct VerifyRequestHandle;
+
+struct DelegationSetQueueEntry;
+
+
+struct DelegationChainEntry
+{
+  /**
+   * DLL
+   */
+  struct DelegationChainEntry *next;
+
+  /**
+   * DLL
+   */
+  struct DelegationChainEntry *prev;
+
+  /**
+   * The issuer
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+  
+  /**
+   * The subject
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+  
+  /**
+   * The issued attribute
+   */
+  char *issuer_attribute;
+  
+  /**
+   * The delegated attribute
+   */
+  char *subject_attribute;
+};
+
+/**
+ * DLL for record
+ */
+struct CredentialRecordEntry
+{
+  /**
+   * DLL
+   */
+  struct CredentialRecordEntry *next;
+
+  /**
+   * DLL
+   */
+  struct CredentialRecordEntry *prev;
+  
+  /**
+   * Number of references in delegation chains
+   */
+  uint32_t refcount;
+
+  /**
+   * Payload
+   */
+  struct GNUNET_CREDENTIAL_Credential *credential;
+};
+
+/**
+ * DLL used for delegations
+ * Used for OR delegations
+ */
+struct DelegationQueueEntry
+{
+  /**
+   * DLL
+   */
+  struct DelegationQueueEntry *next;
+
+  /**
+   * DLL
+   */
+  struct DelegationQueueEntry *prev;
+
+  /**
+   * Sets under this Queue
+   */
+  struct DelegationSetQueueEntry *set_entries_head;
+
+  /**
+   * Sets under this Queue
+   */
+  struct DelegationSetQueueEntry *set_entries_tail;
+
+  /**
+   * Parent set
+   */
+  struct DelegationSetQueueEntry *parent_set;
+
+  /**
+   * Required solutions
+   */
+  uint32_t required_solutions;
+};
+
+/**
+ * DLL for delegation sets
+ * Used for AND delegation set
+ */
+struct DelegationSetQueueEntry
+{
+  /**
+   * DLL
+   */
+  struct DelegationSetQueueEntry *next;
+
+  /**
+   * DLL
+   */
+  struct DelegationSetQueueEntry *prev;
+
+    /**
+   * GNS handle
+   */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
+
+  /**
+   * Verify handle
+   */
+  struct VerifyRequestHandle *handle;
+
+  /**
+   * Parent attribute delegation
+   */
+  struct DelegationQueueEntry *parent;
+
+  /**
+   * Issuer key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
+
+  /**
+   * Queue entries of this set
+   */
+  struct DelegationQueueEntry *queue_entries_head;
+
+  /**
+   * Queue entries of this set
+   */
+  struct DelegationQueueEntry *queue_entries_tail;
+
+  /**
+   * Parent QueueEntry
+   */
+  struct DelegationQueueEntry *parent_queue_entry;
+
+  /**
+   * Issuer attribute delegated to
+   */
+  char *issuer_attribute;
+
+  /**
+   * The current attribute to look up
+   */
+  char *lookup_attribute;
+
+  /**
+   * Trailing attribute context
+   */
+  char *attr_trailer;
+
+  /**
+   * Still to resolve delegation as string
+   */
+  char *unresolved_attribute_delegation;
+
+  /**
+   * The delegation chain entry
+   */
+  struct DelegationChainEntry *delegation_chain_entry;
+
+};
+
+
+/**
+ * Handle to a lookup operation from api
+ */
+struct VerifyRequestHandle
+{
+
+  /**
+   * We keep these in a DLL.
+   */
+  struct VerifyRequestHandle *next;
+
+  /**
+   * We keep these in a DLL.
+   */
+  struct VerifyRequestHandle *prev;
+
+  /**
+   * Handle to the requesting client
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * GNS handle
+   */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
+
+  /**
+   * Size of delegation tree
+   */
+  uint32_t delegation_chain_size;
+
+  /**
+   * Children of this attribute
+   */
+  struct DelegationChainEntry *delegation_chain_head;
+
+  /**
+   * Children of this attribute
+   */
+  struct DelegationChainEntry *delegation_chain_tail;
+
+  /**
+   * Issuer public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * Issuer attribute
+   */
+  char *issuer_attribute;
+
+  /**
+   * Subject public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  /**
+   * Credential DLL
+   */
+  struct CredentialRecordEntry *cred_chain_head;
+
+  /**
+   * Credential DLL
+   */
+  struct CredentialRecordEntry *cred_chain_tail;
+
+  /**
+   * Credential DLL size
+   */
+  uint32_t cred_chain_size;
+
+  /**
+   * Root Delegation Set
+   */
+  struct DelegationSetQueueEntry *root_set;
+
+  /**
+   * Current Delegation Pointer
+   */
+  struct DelegationQueueEntry *current_delegation;
+
+  /**
+   * request id
+   */
+  uint32_t request_id;
+
+  /**
+   * Pending lookups
+   */
+  uint64_t pending_lookups;
+
+  /**
+   * Credential iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
+
+  /**
+   * Collect task
+   */
+  struct GNUNET_SCHEDULER_Task *collect_next_task;
+
+};
+
+
+/**
+ * Head of the DLL.
+ */
+static struct VerifyRequestHandle *vrh_head;
+
+/**
+ * Tail of the DLL.
+ */
+static struct VerifyRequestHandle *vrh_tail;
+
+/**
+ * Handle to the statistics service
+ */
+static struct GNUNET_STATISTICS_Handle *statistics;
+
+/**
+ * Handle to GNS service.
+ */
+static struct GNUNET_GNS_Handle *gns;
+
+
+/**
+ * Handle to namestore service
+ */
+static struct GNUNET_NAMESTORE_Handle *namestore;
+
+static void
+cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
+{
+  struct DelegationQueueEntry *dq_entry;
+  struct DelegationSetQueueEntry *child;
+
+  if (NULL == ds_entry)
+    return;
+
+  for (dq_entry = ds_entry->queue_entries_head;
+       NULL != dq_entry;
+       dq_entry = ds_entry->queue_entries_head)
+  {
+    GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
+                                 ds_entry->queue_entries_tail,
+                                 dq_entry);
+    for (child = dq_entry->set_entries_head;
+         NULL != child;
+         child = dq_entry->set_entries_head)
+    {
+      GNUNET_CONTAINER_DLL_remove (dq_entry->set_entries_head,
+                                   dq_entry->set_entries_tail,
+                                   child);
+      cleanup_delegation_set (child);
+    }
+    GNUNET_free (dq_entry);
+  }
+  GNUNET_free_non_null (ds_entry->issuer_key);
+  GNUNET_free_non_null (ds_entry->lookup_attribute);
+  GNUNET_free_non_null (ds_entry->issuer_attribute);
+  GNUNET_free_non_null (ds_entry->unresolved_attribute_delegation);
+  GNUNET_free_non_null (ds_entry->attr_trailer);
+  if (NULL != ds_entry->lookup_request)
+  {
+    GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
+    ds_entry->lookup_request = NULL;
+  }
+  if (NULL != ds_entry->delegation_chain_entry)
+  {
+    GNUNET_free_non_null (ds_entry->delegation_chain_entry->subject_attribute);
+    GNUNET_free_non_null (ds_entry->delegation_chain_entry->issuer_attribute);
+    GNUNET_free (ds_entry->delegation_chain_entry);
+  }
+  GNUNET_free (ds_entry);
+}
+
+static void
+cleanup_handle (struct VerifyRequestHandle *vrh)
+{
+  struct CredentialRecordEntry *cr_entry;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up...\n");
+  if (NULL != vrh->lookup_request)
+  {
+    GNUNET_GNS_lookup_cancel (vrh->lookup_request);
+    vrh->lookup_request = NULL;
+  }
+  cleanup_delegation_set (vrh->root_set);
+  GNUNET_free_non_null (vrh->issuer_attribute);
+  for (cr_entry = vrh->cred_chain_head; 
+       NULL != vrh->cred_chain_head;
+       cr_entry = vrh->cred_chain_head)
+  {
+    GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
+                                 vrh->cred_chain_tail,
+                                 cr_entry);
+    GNUNET_free_non_null (cr_entry->credential);
+    GNUNET_free (cr_entry);
+  }
+  GNUNET_free (vrh);
+}
+
+static void
+shutdown_task (void *cls)
+{
+  struct VerifyRequestHandle *vrh;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Shutting down!\n");
+
+  while (NULL != (vrh = vrh_head))
+  {
+    //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
+    GNUNET_CONTAINER_DLL_remove (vrh_head,
+                                 vrh_tail,
+                                 vrh);
+    cleanup_handle (vrh);
+  }
+
+  if (NULL != gns)
+  {
+    GNUNET_GNS_disconnect (gns);
+    gns = NULL;
+  }
+  if (NULL != namestore)
+  {
+    GNUNET_NAMESTORE_disconnect (namestore);
+    namestore = NULL;
+  }
+  if (NULL != statistics)
+  {
+    GNUNET_STATISTICS_destroy (statistics,
+                               GNUNET_NO);
+    statistics = NULL;
+  }
+
+}
+
+
+
+static void
+send_lookup_response (struct VerifyRequestHandle *vrh)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct DelegationChainResultMessage *rmsg;
+  struct DelegationChainEntry *dce;
+  struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
+  struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
+  struct CredentialRecordEntry *cd;
+  struct CredentialRecordEntry *tmp;
+  size_t size;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending response\n");
+  dce = vrh->delegation_chain_head;
+  for (uint32_t i=0;i<vrh->delegation_chain_size;i++)
+  {
+    dd[i].issuer_key = dce->issuer_key;
+    dd[i].subject_key = dce->subject_key;
+    dd[i].issuer_attribute = dce->issuer_attribute;
+    dd[i].issuer_attribute_len = strlen (dce->issuer_attribute)+1;
+    dd[i].subject_attribute_len = 0;
+    dd[i].subject_attribute = NULL;
+    if (NULL != dce->subject_attribute)
+    {
+      dd[i].subject_attribute = dce->subject_attribute;
+      dd[i].subject_attribute_len = strlen(dce->subject_attribute)+1;
+    }
+    dce = dce->next;
+  }
+
+  /**
+   * Remove all credentials not needed
+   */
+  for (cd = vrh->cred_chain_head; NULL != cd;)
+  {
+    if (cd->refcount > 0)
+    {
+      cd = cd->next;
+      continue;
+    }
+    tmp = cd;
+    cd = cd->next;
+    GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
+                                 vrh->cred_chain_tail,
+                                 tmp);
+    GNUNET_free (tmp->credential);
+    GNUNET_free (tmp);
+    vrh->cred_chain_size--;
+  }
+
+  /**
+   * Get serialized record data
+   * Append at the end of rmsg
+   */
+  cd = vrh->cred_chain_head;
+  for (uint32_t i=0;i<vrh->cred_chain_size;i++)
+  {
+    cred[i].issuer_key = cd->credential->issuer_key;
+    cred[i].subject_key = cd->credential->subject_key;
+    cred[i].issuer_attribute_len = strlen(cd->credential->issuer_attribute)+1;
+    cred[i].issuer_attribute = cd->credential->issuer_attribute;
+    cred[i].expiration = cd->credential->expiration;
+    cred[i].signature = cd->credential->signature;
+    cd = cd->next;
+  }
+  size = GNUNET_CREDENTIAL_delegation_chain_get_size 
(vrh->delegation_chain_size,
+                                                      dd,
+                                                      vrh->cred_chain_size,
+                                                      cred);
+  env = GNUNET_MQ_msg_extra (rmsg,
+                             size,
+                             GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
+  //Assign id so that client can find associated request
+  rmsg->id = vrh->request_id;
+  rmsg->d_count = htonl (vrh->delegation_chain_size);
+  rmsg->c_count = htonl (vrh->cred_chain_size);
+
+  if (0 < vrh->cred_chain_size)
+    rmsg->cred_found = htonl (GNUNET_YES);
+  else
+    rmsg->cred_found = htonl (GNUNET_NO);
+
+  GNUNET_assert (-1 != 
+                 GNUNET_CREDENTIAL_delegation_chain_serialize 
(vrh->delegation_chain_size,
+                                                               dd,
+                                                               
vrh->cred_chain_size,
+                                                               cred,
+                                                               size,
+                                                               
(char*)&rmsg[1]));
+
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
+                  env);
+  GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
+  cleanup_handle(vrh);
+
+  GNUNET_STATISTICS_update (statistics,
+                            "Completed verifications", 1,
+                            GNUNET_NO);
+}
+
+
+static void
+backward_resolution (void* cls,
+                     uint32_t rd_count,
+                     const struct GNUNET_GNSRECORD_Data *rd)
+{
+
+  struct VerifyRequestHandle *vrh;
+  const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
+  struct CredentialRecordEntry *cred_pointer;
+  struct DelegationSetQueueEntry *current_set;
+  struct DelegationSetQueueEntry *ds_entry;
+  struct DelegationSetQueueEntry *tmp_set;
+  struct DelegationQueueEntry *dq_entry;
+  char *expanded_attr;
+  char *lookup_attribute;
+
+
+  current_set = cls;
+  current_set->lookup_request = NULL;
+  vrh = current_set->handle;
+  vrh->pending_lookups--;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got %d attrs\n", rd_count);
+
+  // Each OR
+  for (uint32_t i=0; i < rd_count; i++) 
+  {
+    if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
+      continue;
+
+    sets = rd[i].data;
+    struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Found new attribute delegation with %d sets. Creating new 
Job...\n",
+                ntohl (sets->set_count));
+
+    if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize 
(GNUNET_ntohll(sets->data_size),
+                                                                  (const 
char*)&sets[1],
+                                                                  
ntohl(sets->set_count),
+                                                                  set))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to deserialize!\n");
+      continue;
+    }
+    dq_entry = GNUNET_new (struct DelegationQueueEntry);
+    dq_entry->required_solutions = ntohl(sets->set_count);
+    dq_entry->parent_set = current_set;
+    GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
+                                 current_set->queue_entries_tail,
+                                 dq_entry);
+    // Each AND
+    for (uint32_t j=0; j<ntohl(sets->set_count); j++)
+    {
+      ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
+      if (NULL != current_set->attr_trailer)
+      {
+        if (0 == set[j].subject_attribute_len)
+        {
+          GNUNET_asprintf (&expanded_attr,
+                           "%s",
+                           current_set->attr_trailer);
+
+        } else {
+          GNUNET_asprintf (&expanded_attr,
+                           "%s.%s",
+                           set[j].subject_attribute,
+                           current_set->attr_trailer);
+        }
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Expanded to %s\n", expanded_attr);
+        ds_entry->unresolved_attribute_delegation = expanded_attr;
+      } else {
+        if (0 != set[j].subject_attribute_len)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "Not Expanding %s\n", set[j].subject_attribute);
+          ds_entry->unresolved_attribute_delegation = GNUNET_strdup 
(set[j].subject_attribute);
+        }
+      }
+
+      //Add a credential chain entry
+      ds_entry->delegation_chain_entry = GNUNET_new (struct 
DelegationChainEntry);
+      ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
+      ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+      GNUNET_memcpy (ds_entry->issuer_key,
+                     &set[j].subject_key,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+      if (0 < set[j].subject_attribute_len)
+        ds_entry->delegation_chain_entry->subject_attribute =  GNUNET_strdup 
(set[j].subject_attribute);
+      ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
+      ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup 
(current_set->lookup_attribute);
+
+      ds_entry->parent_queue_entry = dq_entry; //current_delegation;
+      GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
+                                   dq_entry->set_entries_tail,
+                                   ds_entry);
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Checking for cred match\n");
+      /**
+       * Check if this delegation already matches one of our credentials
+       */
+      for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL; 
+          cred_pointer = cred_pointer->next)
+      {
+        if(0 != memcmp (&set->subject_key, 
+                        &cred_pointer->credential->issuer_key,
+                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+          continue;
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Checking if %s matches %s\n",
+                    ds_entry->unresolved_attribute_delegation,
+                    cred_pointer->credential->issuer_attribute);
+
+        if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
+                         cred_pointer->credential->issuer_attribute))
+          continue;
+
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Found issuer\n");
+        cred_pointer->refcount++;
+        //Backtrack
+        for (tmp_set = ds_entry;
+             NULL != tmp_set->parent_queue_entry;
+             tmp_set = tmp_set->parent_queue_entry->parent_set)
+        {
+          tmp_set->parent_queue_entry->required_solutions--;
+          if (NULL != tmp_set->delegation_chain_entry)
+          {
+            vrh->delegation_chain_size++;
+            GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
+                                         vrh->delegation_chain_tail,
+                                         tmp_set->delegation_chain_entry);
+          }
+          if (0 < tmp_set->parent_queue_entry->required_solutions)
+            break;
+        }
+
+        if (NULL == tmp_set->parent_queue_entry)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "All solutions found\n");
+          //Found match
+          send_lookup_response (vrh);
+          return;
+        }
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Not all solutions found yet.\n");
+        continue;
+
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Building new lookup request from %s\n",
+                  ds_entry->unresolved_attribute_delegation);
+      //Continue with backward resolution
+      char issuer_attribute_name[strlen 
(ds_entry->unresolved_attribute_delegation)+1];
+      strcpy (issuer_attribute_name,
+              ds_entry->unresolved_attribute_delegation);
+      char *next_attr = strtok (issuer_attribute_name, ".");
+      GNUNET_asprintf (&lookup_attribute,
+                       "%s.gnu",
+                       next_attr);
+      GNUNET_asprintf (&ds_entry->lookup_attribute,
+                       "%s",
+                       next_attr);
+      if (strlen (next_attr) == strlen 
(ds_entry->unresolved_attribute_delegation))
+      {
+        ds_entry->attr_trailer = NULL;
+      } else {
+        next_attr += strlen (next_attr) + 1;
+        ds_entry->attr_trailer = GNUNET_strdup (next_attr);
+      }
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Looking up %s\n", ds_entry->lookup_attribute);
+      if (NULL != ds_entry->attr_trailer)
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "%s still to go...\n", ds_entry->attr_trailer);
+
+      vrh->pending_lookups++;
+      ds_entry->handle = vrh;
+      ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
+                                                    lookup_attribute,
+                                                    ds_entry->issuer_key, 
//issuer_key,
+                                                    
GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
+                                                    GNUNET_GNS_LO_DEFAULT,
+                                                    &backward_resolution,
+                                                    ds_entry);
+      GNUNET_free (lookup_attribute);
+    }
+  }
+
+  if(0 == vrh->pending_lookups)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "We are all out of attributes...\n");
+    send_lookup_response (vrh);
+    return;
+
+  }
+} 
+
+
+/**
+ * Result from GNS lookup.
+ *
+ * @param cls the closure (our client lookup handle)
+ */
+static void
+delegation_chain_resolution_start (void* cls)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  struct DelegationSetQueueEntry *ds_entry;
+  struct CredentialRecordEntry *cr_entry;
+  vrh->lookup_request = NULL;
+
+  if (0 == vrh->cred_chain_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No credentials found\n");
+    send_lookup_response (vrh);
+    return;
+  }
+
+  for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = 
cr_entry->next)
+  {
+    if (0 != memcmp (&cr_entry->credential->issuer_key,
+                     &vrh->issuer_key,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      continue;
+    if (0 != strcmp (cr_entry->credential->issuer_attribute, 
vrh->issuer_attribute))
+      continue;
+    cr_entry->refcount++;
+    //Found match prematurely
+    send_lookup_response (vrh);
+    return;
+
+  }
+
+  /**
+   * Check for attributes from the issuer and follow the chain 
+   * till you get the required subject's attributes
+   */
+  char issuer_attribute_name[strlen (vrh->issuer_attribute)];
+  strcpy (issuer_attribute_name,
+          vrh->issuer_attribute);
+  strcpy (issuer_attribute_name + strlen (vrh->issuer_attribute),
+          ".gnu");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Looking up %s\n", issuer_attribute_name);
+  ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
+  ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+  memcpy (ds_entry->issuer_key,
+          &vrh->issuer_key,
+          sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
+  ds_entry->handle = vrh;
+  ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
+  vrh->root_set = ds_entry;
+  vrh->pending_lookups = 1;
+  //Start with backward resolution
+  ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
+                                                issuer_attribute_name,
+                                                &vrh->issuer_key, //issuer_key,
+                                                
GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
+                                                GNUNET_GNS_LO_DEFAULT,
+                                                &backward_resolution,
+                                                ds_entry);
+}
+
+static int
+check_verify (void *cls,
+              const struct VerifyMessage *v_msg)
+{
+  size_t msg_size;
+  const char* attr;
+
+  msg_size = ntohs (v_msg->header.size);
+  if (msg_size < sizeof (struct VerifyMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  attr = (const char *) &v_msg[1];
+
+  if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+static void
+handle_verify (void *cls,
+               const struct VerifyMessage *v_msg) 
+{
+  struct VerifyRequestHandle *vrh;
+  struct GNUNET_SERVICE_Client *client = cls;
+  struct CredentialRecordEntry *cr_entry;
+  uint32_t credentials_count;
+  uint32_t credential_data_size;
+  char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+  char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+  char *attrptr = attr;
+  char *credential_data;
+  const char *utf_in;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received VERIFY message\n");
+  utf_in = (const char *) &v_msg[1];
+  GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
+  GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
+  issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
+  vrh = GNUNET_new (struct VerifyRequestHandle);
+  GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
+  vrh->client = client;
+  vrh->request_id = v_msg->id;
+  vrh->issuer_key = v_msg->issuer_key;
+  vrh->subject_key = v_msg->subject_key;
+  vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
+  if (NULL == issuer_attribute)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                "No issuer attribute provided!\n");
+    send_lookup_response (vrh);
+    return;
+  }
+  /**
+   * First, collect credentials
+   * TODO: cleanup!
+   */
+  credentials_count = ntohl(v_msg->c_count);
+  credential_data_size = ntohs (v_msg->header.size) 
+    - sizeof (struct VerifyMessage)
+    - ntohs (v_msg->issuer_attribute_len)
+    - 1;
+  struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
+  credential_data = (char*)&v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
+  if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize 
(credential_data_size,
+                                                              credential_data,
+                                                              
credentials_count,
+                                                              credentials))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                "Cannot deserialize credentials!\n");
+    send_lookup_response (vrh);
+    return;
+  }
+
+  for (uint32_t i=0;i<credentials_count;i++) {
+    cr_entry = GNUNET_new (struct CredentialRecordEntry);
+    cr_entry->credential = GNUNET_malloc (sizeof (struct 
GNUNET_CREDENTIAL_Credential) +
+                                          credentials[i].issuer_attribute_len);
+    GNUNET_memcpy (cr_entry->credential,
+                   &credentials[i],
+                   sizeof (struct GNUNET_CREDENTIAL_Credential));
+    GNUNET_memcpy (&cr_entry->credential[1],
+                   credentials[i].issuer_attribute,
+                   credentials[i].issuer_attribute_len);
+    cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
+    GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+                                      vrh->cred_chain_tail,
+                                      cr_entry);
+    vrh->cred_chain_size++;
+  }
+
+  delegation_chain_resolution_start (vrh);
+
+}
+
+static void
+handle_cred_collection_error_cb (void *cls)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got disconnected from namestore database.\n");
+  vrh->cred_collection_iter = NULL;
+  send_lookup_response (vrh);
+}
+
+static void
+collect_next (void *cls)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  vrh->collect_next_task = NULL;
+  GNUNET_assert (NULL != vrh->cred_collection_iter);
+  GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
+}
+
+static void
+handle_cred_collection_cb (void *cls,
+                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+                           const char *label,
+                           unsigned int rd_count,
+                           const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  struct GNUNET_CREDENTIAL_Credential *crd;
+  struct CredentialRecordEntry *cr_entry;
+  int cred_record_count;
+
+  cred_record_count = 0;
+  for (uint32_t i=0; i < rd_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
+      continue;
+    cred_record_count++;
+    crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
+                                                    rd[i].data_size);
+    if (NULL == crd)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Invalid credential found\n");
+      continue;
+    }
+    cr_entry = GNUNET_new (struct CredentialRecordEntry);
+    cr_entry->credential = crd;
+    GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+                                      vrh->cred_chain_tail,
+                                      cr_entry);
+    vrh->cred_chain_size++;
+  }
+  vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
+                                                     vrh);
+}
+
+static void
+handle_cred_collection_finished_cb (void *cls)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Done collecting credentials.\n");
+  vrh->cred_collection_iter = NULL;
+  delegation_chain_resolution_start (vrh);
+}
+
+static void
+handle_collect (void *cls,
+                const struct CollectMessage *c_msg) 
+{
+  char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+  char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+  struct VerifyRequestHandle *vrh;
+  struct GNUNET_SERVICE_Client *client = cls;
+  char *attrptr = attr;
+  const char *utf_in;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received COLLECT message\n");
+
+  utf_in = (const char *) &c_msg[1];
+  GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
+
+  GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
+  issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
+  vrh = GNUNET_new (struct VerifyRequestHandle);
+  GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
+  vrh->client = client;
+  vrh->request_id = c_msg->id;
+  vrh->issuer_key = c_msg->issuer_key;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
+                                      &vrh->subject_key);
+  vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
+
+  if (NULL == issuer_attribute)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                "No issuer attribute provided!\n");
+    send_lookup_response (vrh);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting credentials for subject\n");
+  /**
+   * First, get attribute from subject
+   */
+  vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
+                                                                     
&c_msg->subject_key,
+                                                                     
&handle_cred_collection_error_cb,
+                                                                     vrh,
+                                                                     
&handle_cred_collection_cb,
+                                                                     vrh,
+                                                                     
&handle_cred_collection_finished_cb,
+                                                                     vrh);
+}
+
+
+static int
+check_collect (void *cls,
+               const struct CollectMessage *c_msg)
+{
+  size_t msg_size;
+  const char* attr;
+
+  msg_size = ntohs (c_msg->header.size);
+  if (msg_size < sizeof (struct CollectMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  attr = (const char *) &c_msg[1];
+
+  if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct 
CollectMessage) - 1]) ||
+       (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+static void
+client_disconnect_cb (void *cls,
+                      struct GNUNET_SERVICE_Client *client,
+                      void *app_ctx)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client %p disconnected\n",
+              client);
+}
+
+static void *
+client_connect_cb (void *cls,
+                   struct GNUNET_SERVICE_Client *client,
+                   struct GNUNET_MQ_Handle *mq)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client %p connected\n",
+              client);
+  return client;
+}
+
+/**
+ * Process Credential requests.
+ *
+ * @param cls closure
+ * @param c configuration to use
+ * @param handle service handle
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *c,
+     struct GNUNET_SERVICE_Handle *handle)
+{
+
+  gns = GNUNET_GNS_connect (c);
+  if (NULL == gns)
+  {
+    fprintf (stderr,
+             _("Failed to connect to GNS\n"));
+  }
+  namestore = GNUNET_NAMESTORE_connect (c);
+  if (NULL == namestore)
+  {
+    fprintf (stderr,
+             _("Failed to connect to namestore\n"));
+  }
+
+  statistics = GNUNET_STATISTICS_create ("credential", c);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+}
+
+
+/**
+ * Define "main" method using service macro
+ */
+GNUNET_SERVICE_MAIN
+("credential",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (verify,
+                        GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
+                        struct VerifyMessage,
+                        NULL),
+ GNUNET_MQ_hd_var_size (collect,
+                        GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
+                        struct CollectMessage,
+                        NULL),
+ GNUNET_MQ_handler_end());
+
+/* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_gnsrecord_credential.c 
b/src/credential/plugin_gnsrecord_credential.c
new file mode 100644
index 000000000..342790b7a
--- /dev/null
+++ b/src/credential/plugin_gnsrecord_credential.c
@@ -0,0 +1,353 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2013 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file credential/plugin_gnsrecord_credential.c
+ * @brief gnsrecord plugin to provide the API for CREDENTIAL records
+ * @author Martin Schanzenbach
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_credential_service.h"
+#include "gnunet_gnsrecord_plugin.h"
+#include "gnunet_signatures.h"
+#include "credential_serialization.h"
+#include "credential_misc.h"
+
+/**
+ * Convert the 'value' of a record to a string.
+ *
+ * @param cls closure, unused
+ * @param type type of the record
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+static char *
+credential_value_to_string (void *cls,
+                              uint32_t type,
+                              const void *data,
+                              size_t data_size)
+{
+
+  const char *cdata;
+
+  switch (type)
+  {
+   case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
+   {
+    struct GNUNET_CREDENTIAL_DelegationRecord sets;
+    char *attr_str;
+    char *subject_pkey;
+    char *tmp_str;
+    int i;
+    if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
+      return NULL; /* malformed */
+    memcpy (&sets,
+            data,
+            sizeof (sets));
+    cdata = data;
+    struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
+    if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize 
(GNUNET_ntohll (sets.data_size),
+                                                                   
&cdata[sizeof (sets)],
+                                                                   ntohl 
(sets.set_count),
+                                                                   set))
+      return NULL;
+
+    for (i=0;i<ntohl(sets.set_count);i++)
+    {
+      subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string 
(&set[i].subject_key);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "%d len attr\n", set[i].subject_attribute_len);
+      if (0 == set[i].subject_attribute_len)
+      {
+        if (0 == i)
+        {
+          GNUNET_asprintf (&attr_str,
+                           "%s",
+                           subject_pkey);
+        } else {
+          GNUNET_asprintf (&tmp_str,
+                           "%s,%s",
+                           attr_str,
+                           subject_pkey);
+          GNUNET_free (attr_str);
+          attr_str = tmp_str;
+        }
+      } else {
+        if (0 == i)
+        {
+          GNUNET_asprintf (&attr_str,
+                           "%s %s",
+                           subject_pkey,
+                           set[i].subject_attribute);
+        } else {
+          GNUNET_asprintf (&tmp_str,
+                           "%s,%s %s",
+                           attr_str,
+                           subject_pkey,
+                           set[i].subject_attribute);
+          GNUNET_free (attr_str);
+          attr_str = tmp_str;
+        }
+      }
+      GNUNET_free (subject_pkey);
+    }
+    return attr_str;
+   }
+   case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
+   {
+     struct GNUNET_CREDENTIAL_Credential *cred;
+     char *cred_str;
+
+     cred = GNUNET_CREDENTIAL_credential_deserialize (data,
+                                                      data_size);
+     cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
+     GNUNET_free (cred);
+     return cred_str;
+   }
+   case GNUNET_GNSRECORD_TYPE_POLICY:
+   {
+     return GNUNET_strndup (data,data_size);
+   }
+   default:
+   return NULL;
+  }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of a record to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the record
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+credential_string_to_value (void *cls,
+                            uint32_t type,
+                            const char *s,
+                            void **data,
+                            size_t *data_size)
+{
+  if (NULL == s)
+    return GNUNET_SYSERR;
+  switch (type)
+  {
+    case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
+      {
+        struct GNUNET_CREDENTIAL_DelegationRecord *sets;
+        char attr_str[253 + 1];
+        char subject_pkey[52 + 1];
+        char *token;
+        char *tmp_str;
+        int matches = 0;
+        int entries;
+        size_t tmp_data_size;
+        int i;
+
+        tmp_str = GNUNET_strdup (s);
+        token = strtok (tmp_str, ",");
+        entries = 0;
+        tmp_data_size = 0;
+        *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
+        while (NULL != token)
+        {
+          matches = SSCANF (token,
+                            "%s %s",
+                            subject_pkey,
+                            attr_str);
+          if (0 == matches)
+          {
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        _("Unable to parse ATTR record string `%s'\n"),
+                        s);
+            GNUNET_free (tmp_str);
+            return GNUNET_SYSERR;
+          }
+          if (1 == matches) {
+            tmp_data_size += sizeof (struct 
GNUNET_CREDENTIAL_DelegationRecordSet);
+          } else if (2 == matches) {
+            tmp_data_size += sizeof (struct 
GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
+          }
+          entries++;
+          token = strtok (NULL, ",");
+        }
+        GNUNET_free (tmp_str);
+        tmp_str = GNUNET_strdup (s);
+        token = strtok (tmp_str, ",");
+        struct GNUNET_CREDENTIAL_DelegationSet set[entries];
+        for (i=0;i<entries;i++)
+        {
+          matches = SSCANF (token,
+                            "%s %s",
+                            subject_pkey,
+                            attr_str);
+          GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
+                                                      strlen (subject_pkey),
+                                                      &set[i].subject_key);
+          if (2 == matches) {
+            set[i].subject_attribute_len = strlen (attr_str) + 1;
+            set[i].subject_attribute = GNUNET_strdup (attr_str);
+          }
+          token = strtok (NULL , ",");
+        }
+        tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
+                                                                   set);
+        
+        if (-1 == tmp_data_size)
+          return GNUNET_SYSERR;
+        *data_size += tmp_data_size;
+        *data = sets = GNUNET_malloc (*data_size);
+        GNUNET_CREDENTIAL_delegation_set_serialize (entries,
+                                                    set,
+                                                    tmp_data_size,
+                                                    (char*)&sets[1]);
+        for (i=0;i<entries;i++)
+        {
+          if (0 != set[i].subject_attribute_len)
+            GNUNET_free ((char*)set[i].subject_attribute);
+        }
+        sets->set_count = htonl (entries);
+        sets->data_size = GNUNET_htonll (tmp_data_size);
+
+        GNUNET_free (tmp_str);
+        return GNUNET_OK;
+      }
+    case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
+      { 
+        struct GNUNET_CREDENTIAL_Credential *cred;
+        cred = GNUNET_CREDENTIAL_credential_from_string (s);
+
+        *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
+                                                             (char**)data);
+        return GNUNET_OK;
+      }
+    case GNUNET_GNSRECORD_TYPE_POLICY:
+      {
+        *data_size = strlen (s);
+        *data = GNUNET_strdup (s);
+        return GNUNET_OK;
+      }
+    default:
+      return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Mapping of record type numbers to human-readable
+ * record type names.
+ */
+static struct {
+  const char *name;
+  uint32_t number;
+} name_map[] = {
+  { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
+  { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
+  { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
+  { NULL, UINT32_MAX }
+};
+
+
+/**
+ * Convert a type name (i.e. "AAAA") to the corresponding number.
+ *
+ * @param cls closure, unused
+ * @param gns_typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+static uint32_t
+credential_typename_to_number (void *cls,
+                               const char *gns_typename)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (name_map[i].name != NULL) &&
+          (0 != strcasecmp (gns_typename, name_map[i].name)) )
+    i++;
+  return name_map[i].number;
+}
+
+
+/**
+ * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
+ *
+ * @param cls closure, unused
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+static const char *
+credential_number_to_typename (void *cls,
+                               uint32_t type)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (name_map[i].name != NULL) &&
+          (type != name_map[i].number) )
+    i++;
+  return name_map[i].name;
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls NULL
+ * @return the exported block API
+ */
+void *
+libgnunet_plugin_gnsrecord_credential_init (void *cls)
+{
+  struct GNUNET_GNSRECORD_PluginFunctions *api;
+
+  api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
+  api->value_to_string = &credential_value_to_string;
+  api->string_to_value = &credential_string_to_value;
+  api->typename_to_number = &credential_typename_to_number;
+  api->number_to_typename = &credential_number_to_typename;
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the return value from #libgnunet_plugin_block_test_init
+ * @return NULL
+ */
+void *
+libgnunet_plugin_gnsrecord_credential_done (void *cls)
+{
+  struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
+
+  GNUNET_free (api);
+  return NULL;
+}
+
+/* end of plugin_gnsrecord_credential.c */
diff --git a/src/credential/plugin_rest_credential.c 
b/src/credential/plugin_rest_credential.c
new file mode 100644
index 000000000..480658822
--- /dev/null
+++ b/src/credential/plugin_rest_credential.c
@@ -0,0 +1,1146 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2016 GNUnet e.V.
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file credential/plugin_rest_credential.c
+ * @brief GNUnet CREDENTIAL REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include <gnunet_identity_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_credential_service.h>
+#include <gnunet_rest_lib.h>
+#include <gnunet_jsonapi_lib.h>
+#include <gnunet_jsonapi_util.h>
+#include <jansson.h>
+
+#define GNUNET_REST_API_NS_CREDENTIAL "/credential"
+
+#define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue"
+
+#define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify"
+
+#define GNUNET_REST_API_NS_CREDENTIAL_COLLECT "/credential/collect"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO "subject"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL "credential"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential"
+
+#define GNUNET_REST_JSONAPI_DELEGATIONS "delegations"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR "attribute"
+
+#define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_ATTR "credential"
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+struct RequestHandle
+{
+  /**
+   * Handle to Credential service.
+   */
+  struct GNUNET_CREDENTIAL_Handle *credential;
+
+  /**
+   * Handle to lookup request
+   */
+  struct GNUNET_CREDENTIAL_Request *verify_request;
+
+  /**
+   * Handle to issue request
+   */
+  struct GNUNET_CREDENTIAL_Request *issue_request;
+
+  /**
+   * Handle to identity
+   */
+  struct GNUNET_IDENTITY_Handle *identity;
+
+  /**
+   * Handle to identity operation
+   */
+  struct GNUNET_IDENTITY_Operation *id_op;
+
+  /**
+   * Handle to ego lookup
+   */
+  struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
+
+  /**
+   * Handle to rest request
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task * timeout_task;
+
+  /**
+   * The root of the received JSON or NULL
+   */
+  json_t *json_root;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The issuer attribute to verify
+   */
+  char *issuer_attr;
+
+  /**
+   * The subject attribute
+   */
+  char *subject_attr;
+
+  /**
+   * The public key of the issuer
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * The public key of the subject
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  /**
+   * HTTP response code
+   */
+  int response_code;
+
+  /**
+   * Timeout
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+};
+
+
+/**
+ * Cleanup lookup handle.
+ *
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->json_root)
+    json_decref (handle->json_root);
+
+  if (NULL != handle->issuer_attr)
+    GNUNET_free (handle->issuer_attr);
+  if (NULL != handle->subject_attr)
+    GNUNET_free (handle->subject_attr);
+  if (NULL != handle->verify_request)
+    GNUNET_CREDENTIAL_request_cancel (handle->verify_request);
+  if (NULL != handle->credential)
+    GNUNET_CREDENTIAL_disconnect (handle->credential);
+  if (NULL != handle->id_op)
+    GNUNET_IDENTITY_cancel (handle->id_op);
+  if (NULL != handle->ego_lookup)
+    GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
+  if (NULL != handle->identity)
+    GNUNET_IDENTITY_disconnect (handle->identity);
+  if (NULL != handle->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+  }
+  GNUNET_free (handle);
+}
+
+
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  resp = GNUNET_REST_create_response (NULL);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  cleanup_handle (handle);
+}
+
+/**
+ * Attribute delegation to JSON
+ *
+ * @param delegation_chain_entry the DSE
+ * @return JSON, NULL if failed
+ */
+static json_t*
+attribute_delegation_to_json (struct GNUNET_CREDENTIAL_Delegation 
*delegation_chain_entry)
+{
+  char *subject;
+  char *issuer;
+  json_t *attr_obj;
+
+  issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string 
(&delegation_chain_entry->issuer_key);
+  if (NULL == issuer)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Issuer in delegation malformed\n");
+    return NULL;
+  }
+  subject = GNUNET_CRYPTO_ecdsa_public_key_to_string 
(&delegation_chain_entry->subject_key);
+  if (NULL == subject)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Subject in credential malformed\n");
+    GNUNET_free (issuer);
+    return NULL;
+  }
+  attr_obj = json_object ();
+
+    json_object_set_new (attr_obj, "issuer", json_string (issuer));
+  json_object_set_new (attr_obj, "issuer_attribute",
+                       json_string (delegation_chain_entry->issuer_attribute));
+
+  json_object_set_new (attr_obj, "subject", json_string (subject));
+  if (0 < delegation_chain_entry->subject_attribute_len)
+  {
+    json_object_set_new (attr_obj, "subject_attribute",
+                         json_string 
(delegation_chain_entry->subject_attribute));
+  }
+  GNUNET_free (issuer);
+  GNUNET_free (subject);
+  return attr_obj;
+}
+
+/**
+ * JSONAPI resource to Credential
+ *
+ * @param res the JSONAPI resource
+ * @return the resulting credential, NULL if failed
+ */
+static struct GNUNET_CREDENTIAL_Credential*
+json_to_credential (json_t *res)
+{
+  struct GNUNET_CREDENTIAL_Credential *cred;
+  json_t *tmp;
+  const char *attribute;
+  const char *signature;
+  char *sig;
+
+  tmp = json_object_get (res, "attribute");
+  if (0 == json_is_string (tmp))
+  {
+    return NULL;
+  }
+  attribute = json_string_value (tmp);
+  cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential)
+                        + strlen (attribute));
+  cred->issuer_attribute = attribute;
+  cred->issuer_attribute_len = strlen (attribute);
+  tmp = json_object_get (res, "issuer");
+  if (0 == json_is_string (tmp))
+  {
+    GNUNET_free (cred);
+    return NULL;
+  }
+
+  GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
+                                              strlen (json_string_value(tmp)),
+                                              &cred->issuer_key);
+  tmp = json_object_get (res, "subject");
+  if (0 == json_is_string (tmp))
+  {
+    GNUNET_free (cred);
+    return NULL;
+  }
+  GNUNET_CRYPTO_ecdsa_public_key_from_string (json_string_value(tmp),
+                                              strlen (json_string_value(tmp)),
+                                              &cred->subject_key);
+
+  tmp = json_object_get (res, "signature");
+  if (0 == json_is_string (tmp))
+  {
+    GNUNET_free (cred);
+    return NULL;
+  }
+  signature = json_string_value (tmp);
+  GNUNET_STRINGS_base64_decode (signature,
+                                strlen (signature),
+                                (char**)&sig);
+  GNUNET_memcpy (&cred->signature,
+                 sig,
+                 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+  GNUNET_free (sig);
+ 
+  tmp = json_object_get (res, "expiration");
+  if (0 == json_is_integer (tmp))
+  {
+    GNUNET_free (cred);
+    return NULL;
+  }
+  cred->expiration.abs_value_us = json_integer_value (tmp); 
+  return cred;
+}
+
+
+/**
+ * Credential to JSON
+ *
+ * @param cred the credential
+ * @return the resulting json, NULL if failed
+ */
+static json_t*
+credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
+{
+  char *issuer;
+  char *subject;
+  char *signature;
+  char attribute[cred->issuer_attribute_len + 1];
+  json_t *cred_obj;
+
+  issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+  if (NULL == issuer)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Issuer in credential malformed\n");
+    return NULL;
+  }  
+  subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+  if (NULL == subject)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Subject in credential malformed\n");
+    GNUNET_free (issuer);
+    return NULL;
+  }
+  GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
+                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+                                &signature);
+  memcpy (attribute,
+          cred->issuer_attribute,
+          cred->issuer_attribute_len);
+  attribute[cred->issuer_attribute_len] = '\0';
+  cred_obj = json_object ();
+  json_object_set_new (cred_obj, "issuer", json_string (issuer));
+  json_object_set_new (cred_obj, "subject", json_string (subject));
+  json_object_set_new (cred_obj, "attribute", json_string (attribute));
+  json_object_set_new (cred_obj, "signature", json_string (signature));
+  json_object_set_new (cred_obj, "expiration", json_integer 
(cred->expiration.abs_value_us));
+  GNUNET_free (issuer);
+  GNUNET_free (subject);
+  GNUNET_free (signature);
+  return cred_obj;
+}
+
+static void
+handle_collect_response (void *cls,
+                        unsigned int d_count,
+                        struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
+                        unsigned int c_count,
+                        struct GNUNET_CREDENTIAL_Credential *cred)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  struct GNUNET_JSONAPI_Document *json_document;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *cred_obj;
+  json_t *cred_array;
+  char *result;
+  char *issuer;
+  char *id;
+  uint32_t i;
+
+  handle->verify_request = NULL;
+  if (NULL == cred) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Verify failed.\n");
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
+  if (NULL == issuer)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Issuer in delegation malformed\n");
+    return;
+  }
+  GNUNET_asprintf (&id,
+                   "%s.%s",
+                   issuer,
+                   handle->issuer_attr);
+  GNUNET_free (issuer);
+  json_document = GNUNET_JSONAPI_document_new ();
+  json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
+                                               id);
+  GNUNET_free (id);
+  cred_array = json_array ();
+  for (i=0;i<c_count;i++)
+  {
+    cred_obj = credential_to_json (&cred[i]);
+    json_array_append_new (cred_array, cred_obj);
+  }
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    GNUNET_REST_JSONAPI_CREDENTIAL,
+                                    cred_array);
+  GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+  GNUNET_JSONAPI_document_serialize (json_document, &result);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Result %s\n",
+              result);
+  json_decref (cred_array);
+  GNUNET_JSONAPI_document_delete (json_document);
+  resp = GNUNET_REST_create_response (result);
+  GNUNET_free(result);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+}
+
+static void
+subject_ego_lookup (void *cls,
+                    const struct GNUNET_IDENTITY_Ego *ego)
+{
+  struct RequestHandle *handle = cls;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *sub_key;
+  handle->ego_lookup = NULL;
+
+  if (NULL == ego)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Subject not found\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  sub_key = GNUNET_IDENTITY_ego_get_private_key (ego);
+  handle->verify_request = GNUNET_CREDENTIAL_collect (handle->credential,
+                                                      &handle->issuer_key,
+                                                      handle->issuer_attr,
+                                                      sub_key,
+                                                      &handle_collect_response,
+                                                      handle);
+}
+
+
+
+static void
+handle_verify_response (void *cls,
+                        unsigned int d_count,
+                        struct GNUNET_CREDENTIAL_Delegation *delegation_chain,
+                        unsigned int c_count,
+                        struct GNUNET_CREDENTIAL_Credential *cred)
+{
+
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  struct GNUNET_JSONAPI_Document *json_document;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *cred_obj;
+  json_t *attr_obj;
+  json_t *cred_array;
+  json_t *attr_array;
+  char *result;
+  char *issuer;
+  char *id;
+  uint32_t i;
+
+  handle->verify_request = NULL;
+  if (NULL == cred) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Verify failed.\n");
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&handle->issuer_key);
+  if (NULL == issuer)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Issuer in delegation malformed\n");
+    return;
+  }
+  GNUNET_asprintf (&id,
+                   "%s.%s",
+                   issuer,
+                   handle->issuer_attr);
+  GNUNET_free (issuer);
+  json_document = GNUNET_JSONAPI_document_new ();
+  json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
+                                               id);
+  GNUNET_free (id);
+  attr_array = json_array ();
+  for (i = 0; i < d_count; i++)
+  {
+    attr_obj = attribute_delegation_to_json (&delegation_chain[i]);
+    json_array_append_new (attr_array, attr_obj);
+  }
+  cred_array = json_array ();
+  for (i=0;i<c_count;i++)
+  {
+    cred_obj = credential_to_json (&cred[i]);
+    json_array_append_new (cred_array, cred_obj);
+  }
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    GNUNET_REST_JSONAPI_CREDENTIAL,
+                                    cred_array);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    GNUNET_REST_JSONAPI_DELEGATIONS,
+                                    attr_array);
+  GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+  GNUNET_JSONAPI_document_serialize (json_document, &result);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Result %s\n",
+              result);
+  json_decref (attr_array);
+  json_decref (cred_array);
+  GNUNET_JSONAPI_document_delete (json_document);
+  resp = GNUNET_REST_create_response (result);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result);
+  cleanup_handle (handle);
+}
+
+static void
+collect_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+                   const char* url,
+                   void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+  char *tmp;
+  char *entity_attr;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting...\n");
+  handle->credential = GNUNET_CREDENTIAL_connect (cfg);
+  handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                                       &do_error, handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+  if (NULL == handle->credential)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Connecting to CREDENTIAL failed\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
+                      strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing issuer attribute\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+                                           &key);
+  entity_attr = GNUNET_strdup (tmp);
+  tmp = strtok(entity_attr, ".");
+  if (NULL == tmp)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed issuer or attribute\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (GNUNET_OK != 
+      GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+                                                  strlen (tmp),
+                                                  &handle->issuer_key))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed issuer key\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  tmp = strtok (NULL, "."); //Issuer attribute
+  if (NULL == tmp)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed attribute\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->issuer_attr = GNUNET_strdup (tmp);
+  GNUNET_free (entity_attr);
+
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO,
+                      strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_EGO),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing subject\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+                                           &key);
+  if (NULL == tmp)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed subject\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
+                                                   tmp,
+                                                   &subject_ego_lookup,
+                                                   handle);
+}
+
+
+
+static void
+verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+                  const char* url,
+                  void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *res;
+  struct GNUNET_CREDENTIAL_Credential *cred;
+  char *tmp;
+  char *entity_attr;
+  int i;
+  uint32_t credential_count;
+  uint32_t resource_count;
+  json_t *cred_json;
+  json_t *data_js;
+  json_error_t err;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting...\n");
+  handle->credential = GNUNET_CREDENTIAL_connect (cfg);
+  handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                                       &do_error, handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+  if (NULL == handle->credential)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Connecting to CREDENTIAL failed\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
+                      strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing issuer attribute\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+                                           &key);
+  entity_attr = GNUNET_strdup (tmp);
+  tmp = strtok(entity_attr, ".");
+  if (NULL == tmp)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed issuer or attribute\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (GNUNET_OK != 
+      GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+                                                  strlen (tmp),
+                                                  &handle->issuer_key))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed issuer key\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  tmp = strtok (NULL, "."); //Issuer attribute
+  if (NULL == tmp)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed attribute\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->issuer_attr = GNUNET_strdup (tmp);
+  GNUNET_free (entity_attr);
+
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
+                      strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing subject key\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  tmp = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+                                           &key);
+  if (NULL == tmp)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed subject\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+                                                  strlen (tmp),
+                                                  &handle->subject_key)) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed subject key\n");
+    GNUNET_free (entity_attr);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing credentials\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+  char term_data[handle->rest_handle->data_size+1];
+  term_data[handle->rest_handle->data_size] = '\0';
+  credential_count = 0;
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_js = json_loads (term_data,
+                        JSON_DECODE_ANY,
+                        &err);
+  GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, docspec,
+                                                 NULL, NULL));
+  json_decref (data_js);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  resource_count = GNUNET_JSONAPI_document_resource_count(json_obj);
+  GNUNET_assert (1 == resource_count);
+  res = (GNUNET_JSONAPI_document_get_resource(json_obj, 0));
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type(res,
+                                                      
GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Resource not a credential!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  cred_json = GNUNET_JSONAPI_resource_read_attr (res,
+                                                 
GNUNET_REST_JSONAPI_CREDENTIAL);
+
+  GNUNET_assert (json_is_array (cred_json));
+
+  credential_count = json_array_size(cred_json);
+
+  struct GNUNET_CREDENTIAL_Credential credentials[credential_count];
+  for (i=0;i<credential_count;i++)
+  {
+    cred = json_to_credential (json_array_get (cred_json, i));
+    if (NULL == cred)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Unable to parse credential!\n");
+      continue;
+    }
+    GNUNET_memcpy (&credentials[i],
+                   cred,
+                   sizeof (struct GNUNET_CREDENTIAL_Credential));
+    credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
+    GNUNET_free (cred);
+  }
+  GNUNET_JSONAPI_document_delete(json_obj);
+  handle->verify_request = GNUNET_CREDENTIAL_verify (handle->credential,
+                                                     &handle->issuer_key,
+                                                     handle->issuer_attr,
+                                                     &handle->subject_key,
+                                                     credential_count,
+                                                     credentials,
+                                                     &handle_verify_response,
+                                                     handle);
+  for (i=0;i<credential_count;i++)
+    GNUNET_free ((char*)credentials[i].issuer_attribute);
+
+}
+
+void
+send_cred_response (struct RequestHandle *handle,
+                    struct GNUNET_CREDENTIAL_Credential *cred)
+{
+  struct MHD_Response *resp;
+  struct GNUNET_JSONAPI_Document *json_document;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *cred_obj;
+  char *result;
+  char *issuer;
+  char *subject;
+  char *signature;
+  char *id;
+
+  GNUNET_assert (NULL != cred);
+  issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+  if (NULL == issuer)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Subject malformed\n");
+    return;
+  }
+  GNUNET_asprintf (&id,
+                   "%s.%s",
+                   issuer,
+                   (char*)&cred[1]);
+  subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+  if (NULL == subject)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Subject malformed\n");
+    return;
+  }
+  GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
+                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+                                &signature);
+  json_document = GNUNET_JSONAPI_document_new ();
+  json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO,
+                                               id);
+  GNUNET_free (id);
+  cred_obj = json_object();
+  json_object_set_new (cred_obj, "issuer", json_string (issuer));
+  json_object_set_new (cred_obj, "subject", json_string (subject));
+  json_object_set_new (cred_obj, "expiration", json_integer( 
cred->expiration.abs_value_us));
+  json_object_set_new (cred_obj, "signature", json_string (signature));
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    GNUNET_REST_JSONAPI_CREDENTIAL,
+                                    cred_obj);
+  GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+  GNUNET_JSONAPI_document_serialize (json_document, &result);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Result %s\n",
+              result);
+  json_decref (cred_obj);
+  GNUNET_JSONAPI_document_delete (json_document);
+  resp = GNUNET_REST_create_response (result);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result);
+  GNUNET_free (signature);
+  GNUNET_free (issuer);
+  GNUNET_free (subject);
+  cleanup_handle (handle);
+}
+
+void
+get_cred_issuer_cb (void *cls,
+                    struct GNUNET_IDENTITY_Ego *ego,
+                    void **ctx,
+                    const char *name)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_TIME_Absolute etime_abs;
+  struct GNUNET_TIME_Relative etime_rel;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key;
+  struct GNUNET_HashCode key;
+  struct GNUNET_CREDENTIAL_Credential *cred;
+  char* expiration_str;
+  char* tmp;
+
+  handle->id_op = NULL;
+
+  if (NULL == name)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Issuer not configured!\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting to credential service...\n");
+  handle->credential = GNUNET_CREDENTIAL_connect (cfg);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+  if (NULL == handle->credential)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Connecting to CREDENTIAL failed\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION,
+                      strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains 
(handle->rest_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing expiration\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  expiration_str = GNUNET_CONTAINER_multihashmap_get 
(handle->rest_handle->url_param_map,
+                                                      &key);
+  if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str,
+                                                          &etime_rel))
+  {
+    etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel);
+  } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute 
(expiration_str,
+                                                                 &etime_abs))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed expiration: %s\n", expiration_str);
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR,
+                      strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains 
(handle->rest_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing issuer attribute\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get 
+                                      (handle->rest_handle->url_param_map,
+                                       &key));
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY,
+                      strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains 
(handle->rest_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Missing subject\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+                                           &key);
+  if (NULL == tmp)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed subject\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle); 
+    return;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp,
+                                                  strlen (tmp),
+                                                  &handle->subject_key)) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed subject key\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego);
+  cred = GNUNET_CREDENTIAL_credential_issue (issuer_key,
+                                             &handle->subject_key,
+                                             handle->issuer_attr,
+                                             &etime_abs);
+  if (NULL == cred)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to create credential\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  send_cred_response (handle, cred);
+}
+
+
+static void
+issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+                 const char* url,
+                 void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->identity = GNUNET_IDENTITY_connect (cfg,
+                                              NULL,
+                                              NULL);
+  handle->id_op = GNUNET_IDENTITY_get(handle->identity,
+                                      "credential-issuer",
+                                      &get_cred_issuer_cb,
+                                      handle);
+  handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                                       &do_error,
+                                                       handle);
+}
+
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //For GNS, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           MHD_HTTP_METHOD_GET);
+  handle->proc (handle->proc_cls,
+                resp,
+                MHD_HTTP_OK);
+  cleanup_handle (handle);
+}
+
+
+static void
+rest_credential_process_request(struct GNUNET_REST_RequestHandle 
*conndata_handle,
+                                GNUNET_REST_ResultProcessor proc,
+                                void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->rest_handle = conndata_handle;
+
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, 
&verify_cred_cont},
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_COLLECT, 
&collect_cred_cont},
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, 
&issue_cred_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
+                                                  handlers,
+                                                  &err,
+                                                  handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_credential_init (void *cls)
+{
+  static struct Plugin plugin;
+  cfg = cls;
+  struct GNUNET_REST_Plugin *api;
+
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_CREDENTIAL;
+  api->process_request = &rest_credential_process_request;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _("GNS REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_credential_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+
+  plugin->cfg = NULL;
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "GNS REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_gns.c */
diff --git a/src/credential/test_credential_collect.sh 
b/src/credential/test_credential_collect.sh
new file mode 100755
index 000000000..6c713063f
--- /dev/null
+++ b/src/credential/test_credential_collect.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+TEST_ATTR2="test2"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testissuer | awk '{print $3}')
+#TODO1 Get credential and store it with subject (3)
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer 
--subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c 
test_credential_lookup.conf`
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer 
--subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c 
test_credential_lookup.conf`
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY 
--attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste 
-d, -s`
+echo $CREDS
+RES=$?
+gnunet-arm -e -c test_credential_lookup.conf
+
+if test $? != 0
+then
+  echo "Error collecting..."
+  exit 1
+fi
+
diff --git a/src/credential/test_credential_collect_rest.sh 
b/src/credential/test_credential_collect_rest.sh
new file mode 100755
index 000000000..0b31f85bc
--- /dev/null
+++ b/src/credential/test_credential_collect_rest.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) Service.user -> GNU.project.member
+#  (2) GNU.project -> GNUnet
+#  (3) GNUnet.member -> GNUnet.developer
+#  (4) GNUnet.member -> GNUnet.user
+#  (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep 
-v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | 
awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | 
awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service 
| awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been 
assigned "member" by entities that werde assigned "project" from GNU
+gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY 
$GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" 
attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 
5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also 
assigned "developer" or "user"
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY 
$DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY 
$USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY 
--attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY 
--attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+
+#TODO2 Add -z swich like in gnunet-gns
+#RES_CRED=`gnunet-credential --collect --issuer=$SERVICE_KEY 
--attribute=$USER_ATTR --subject=$ALICE_KEY -c test_credential_lookup.conf`
+
+gnunet-arm -i rest -c test_credential_lookup.conf
+
+sleep 5
+
+curl -v 
"localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c 
test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c 
test_credential_lookup.conf
+echo "Stopping arm..."
+gnunet-arm -e -c test_credential_lookup.conf
+echo "Done"
+if [ "$RES_CRED" != "Failed." ]
+then
+  echo -e "${RES_CRED}"
+  exit 0
+else
+  echo "FAIL: Failed to verify credential $RES_CRED."
+  exit 1
+fi
diff --git a/src/gns/test_gns_defaults.conf 
b/src/credential/test_credential_defaults.conf
similarity index 87%
copy from src/gns/test_gns_defaults.conf
copy to src/credential/test_credential_defaults.conf
index 27e9c2c31..d157ddd43 100644
--- a/src/gns/test_gns_defaults.conf
+++ b/src/credential/test_credential_defaults.conf
@@ -1,7 +1,7 @@
 @INLINE@ ../../contrib/no_forcestart.conf
 
 [PATHS]
-GNUNET_TEST_HOME = /tmp/test-gnunet-gns-testing/
+GNUNET_TEST_HOME = /tmp/test-gnunet-credential-testing/
 
 [namestore-sqlite]
 FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
diff --git a/src/credential/test_credential_issue.sh 
b/src/credential/test_credential_issue.sh
new file mode 100755
index 000000000..158d91c5b
--- /dev/null
+++ b/src/credential/test_credential_issue.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testissuer | awk '{print $3}')
+#TODO1 Get credential and store it with subject (3)
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer 
--subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c 
test_credential_lookup.conf`
+STATUS=$?
+
+if test $? != 0
+then
+  echo "Error issuing..."
+  exit 1
+fi
+#Try import
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+RES=$?
+gnunet-arm -e -c test_credential_lookup.conf
+exit $RES
diff --git a/src/credential/test_credential_issue_rest.sh 
b/src/credential/test_credential_issue_rest.sh
new file mode 100755
index 000000000..15cd55083
--- /dev/null
+++ b/src/credential/test_credential_issue_rest.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-arm -i gns
+gnunet-arm -i credential
+gnunet-arm -i identity
+gnunet-arm -i rest -c test_credential_lookup.conf
+
+gnunet-arm -I -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+gnunet-identity -s credential-issuer -e testissuer
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testissuer | awk '{print $3}')
+#TODO1 Get credential and store it with subject (3)
+sleep 5
+curl 
"localhost:7776/credential/issue?subject_key=$SUBJECT_KEY&attribute=$TEST_ATTR&expiration=1d"
+#CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer 
--subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c 
test_credential_lookup.conf`
+STATUS=$?
+
+if test $? != 0
+then
+  echo "Error issuing..."
+  exit 1
+fi
+#Try import
+#$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+RES=$?
+gnunet-arm -e -c test_credential_lookup.conf
+exit $RES
diff --git a/src/gns/test_gns_lookup.conf 
b/src/credential/test_credential_lookup.conf
similarity index 54%
copy from src/gns/test_gns_lookup.conf
copy to src/credential/test_credential_lookup.conf
index ea8c7c3fc..3684063b1 100644
--- a/src/gns/test_gns_lookup.conf
+++ b/src/credential/test_credential_lookup.conf
@@ -1,7 +1,7 @@
address@hidden@ test_gns_defaults.conf
address@hidden@ test_credential_defaults.conf
 
 [PATHS]
-GNUNET_TEST_HOME = /tmp/test-gnunet-gns-peer-1/
+GNUNET_TEST_HOME = /tmp/test-gnunet-credential-peer-1/
 
 [dht]
 AUTOSTART = YES
@@ -9,6 +9,13 @@ AUTOSTART = YES
 [transport]
 PLUGINS =
 
+[credential]
+AUTOSTART = YES
+PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
+
+[rest]
+PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog
+
 [gns]
 #PREFIX = valgrind --leak-check=full --track-origins=yes
 AUTOSTART = YES
@@ -19,5 +26,3 @@ RECORD_PUT_INTERVAL = 1 h
 ZONE_PUBLISH_TIME_WINDOW = 1 h
 DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
 
-[revocation]
-WORKBITS = 1
diff --git a/src/credential/test_credential_verify.sh 
b/src/credential/test_credential_verify.sh
new file mode 100755
index 000000000..d042bcfe6
--- /dev/null
+++ b/src/credential/test_credential_verify.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) Service.user -> GNU.project.member
+#  (2) GNU.project -> GNUnet
+#  (3) GNUnet.member -> GNUnet.developer
+#  (4) GNUnet.member -> GNUnet.user
+#  (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep 
-v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | 
awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | 
awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service 
| awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been 
assigned "member" by entities that werde assigned "project" from GNU
+gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY 
$GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" 
attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 
5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also 
assigned "developer" or "user"
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY 
$DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY 
$USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY 
--attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY 
--attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, 
-s`
+
+echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR 
--subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
+#TODO2 Add -z swich like in gnunet-gns
+gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR 
--subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf
+
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c 
test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+
+if [ "$RES_CRED" != "Failed." ]
+then
+  echo -e "${RES_CRED}"
+  exit 0
+else
+  echo "FAIL: Failed to verify credential $RES_CRED."
+  exit 1
+fi
diff --git a/src/credential/test_credential_verify_and.sh 
b/src/credential/test_credential_verify_and.sh
new file mode 100755
index 000000000..9d5c1962e
--- /dev/null
+++ b/src/credential/test_credential_verify_and.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) Service.user -> GNU.project.member
+#  (2) GNU.project -> GNUnet
+#  (3) GNUnet.member -> GNUnet.developer
+#  (4) GNUnet.member -> GNUnet.user
+#  (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep 
-v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | 
awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | 
awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service 
| awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been 
assigned "member" by entities that werde assigned "project" from GNU
+gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY 
$GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" 
attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 
5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also 
assigned "developer" or "user"
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY 
$DEVELOPER_ATTR,$GNUNET_KEY $USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED1=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY 
--attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+# (5) GNUnet issues Alice the credential "user"
+CRED2=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY 
--attribute=$USER_ATTR --ttl=5m -c test_credential_lookup.conf`
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED1" -e 5m 
-c test_credential_lookup.conf
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED2" -e 5m 
-c test_credential_lookup.conf
+
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY 
--attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, 
-s`
+
+#TODO2 Add -z swich like in gnunet-gns
+RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY 
--attribute=$USER_ATTR --subject=$ALICE_KEY --credential="$CREDS" -c 
test_credential_lookup.conf`
+
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c 
test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+
+if [ "$RES_CRED" != "Failed." ]
+then
+  echo -e "${RES_CRED}"
+  exit 0
+else
+  echo "FAIL: Failed to verify credential $RES_CRED."
+  exit 1
+fi
diff --git a/src/credential/test_credential_verify_rest.sh 
b/src/credential/test_credential_verify_rest.sh
new file mode 100755
index 000000000..6133ea25e
--- /dev/null
+++ b/src/credential/test_credential_verify_rest.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) Service.user -> GNU.project.member
+#  (2) GNU.project -> GNUnet
+#  (3) GNUnet.member -> GNUnet.developer
+#  (4) GNUnet.member -> GNUnet.user
+#  (5) GNUnet.developer -> Alice
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C service -c test_credential_lookup.conf
+gnunet-identity -C alice -c test_credential_lookup.conf
+gnunet-identity -C gnu -c test_credential_lookup.conf
+gnunet-identity -C gnunet -c test_credential_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnu | grep 
-v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep alice | 
awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep gnunet | 
awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep service 
| awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+# (1) A service assigns the attribute "user" to all entities that have been 
assigned "member" by entities that werde assigned "project" from GNU
+gnunet-namestore -p -z service -a -n $USER_ATTR -t ATTR -V "$GNU_KEY 
$GNU_PROJECT_ATTR.$MEMBER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" 
attribute
+gnunet-namestore -p -z gnu -a -n $GNU_PROJECT_ATTR -t ATTR -V "$GNUNET_KEY" -e 
5m -c test_credential_lookup.conf
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also 
assigned "developer" or "user"
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY 
$DEVELOPER_ATTR" -e 5m -c test_credential_lookup.conf
+gnunet-namestore -p -z gnunet -a -n $MEMBER_ATTR -t ATTR -V "$GNUNET_KEY 
$USER_ATTR" -e 5m -c test_credential_lookup.conf
+
+# (5) GNUnet issues Alice the credential "developer"
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet --subject=$ALICE_KEY 
--attribute=$DEV_ATTR --ttl=5m -c test_credential_lookup.conf`
+
+# Alice stores the credential under "mygnunetcreds"
+gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+
+#TODO2 Add -z swich like in gnunet-gns
+#RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY 
--attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c 
test_credential_lookup.conf`
+
+gnunet-arm -i rest -c test_credential_lookup.conf
+
+sleep 5
+
+CREDS=`curl 
"localhost:7776/credential/collect?attribute=$SERVICE_KEY.$USER_ATTR&subject=alice"`
+
+echo $CREDS
+
+curl -v 
"localhost:7776/credential/verify?attribute=$SERVICE_KEY.$USER_ATTR&subject_key=$ALICE_KEY"
 --data "$CREDS"
+
+#TODO cleanup properly
+gnunet-namestore -z alice -d -n $TEST_CREDENTIAL -t CRED -e never -c 
test_credential_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c 
test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+
+if [ "$RES_CRED" != "Failed." ]
+then
+  echo -e "${RES_CRED}"
+  exit 0
+else
+  echo "FAIL: Failed to verify credential $RES_CRED."
+  exit 1
+fi
diff --git a/src/credential/test_credential_verify_simple.sh 
b/src/credential/test_credential_verify_simple.sh
new file mode 100755
index 000000000..c4fd8c7a3
--- /dev/null
+++ b/src/credential/test_credential_verify_simple.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (3) Isser.user -> Subject
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+
+TEST_ATTR="user"
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testissuer | awk '{print $3}')
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer 
--subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c 
test_credential_lookup.conf`
+
+TEST_CREDENTIAL="t1"
+gnunet-namestore -p -z testsubject -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" 
-e 5m -c test_credential_lookup.conf
+
+#TODO2 Add -z swich like in gnunet-gns
+#RES_CRED=`$DO_TIMEOUT gnunet-credential --verify --issuer=$ISSUER_KEY 
--attribute="$TEST_ATTR" --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL 
-c test_credential_lookup.conf`
+RES_CRED=`gnunet-credential --verify --issuer=$ISSUER_KEY 
--attribute=$TEST_ATTR --subject=$SUBJECT_KEY --credential=$TEST_CREDENTIAL -c 
test_credential_lookup.conf`
+
+#TODO cleanup properly
+gnunet-namestore -z testsubject -d -n $TEST_CREDENTIAL -t CRED -e never -c 
test_credential_lookup.conf
+gnunet-identity -D testsubject -c test_credential_lookup.conf
+gnunet-arm -e -c test_credential_lookup.conf
+echo $RES_CRED
+#TODO3 proper test
+if [ "$RES_CRED" == "Successful." ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 7196a1844..d9a5dd684 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -3802,7 +3802,7 @@ run (void *cls,
     if (GNUNET_YES !=
        GNUNET_OS_check_helper_binary (binary,
                                        GNUNET_YES,
-                                       "-d gnunet-vpn - - - 169.1.3.3.7 
255.255.255.0")) //no nat, ipv4 only
+                                       "gnunet-vpn - - - 169.1.3.7 
255.255.255.0")) //no nat, ipv4 only
     {
       GNUNET_free (binary);
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index 26293f4df..84c4ae189 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -244,10 +244,7 @@ handle_result (void *cls,
     return;
   proc = lr->lookup_proc;
   proc_cls = lr->proc_cls;
-  GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
-                               handle->lookup_tail,
-                               lr);
-  GNUNET_free (lr);
+  
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_GNSRECORD_records_deserialize (mlen,
                                                        (const char*) 
&lookup_msg[1],
@@ -256,6 +253,12 @@ handle_result (void *cls,
   proc (proc_cls,
         rd_count,
         rd);
+  GNUNET_CONTAINER_DLL_remove (handle->lookup_head,
+                               handle->lookup_tail,
+                               lr);
+  if (NULL != lr->env)
+    GNUNET_MQ_discard (lr->env);
+  GNUNET_free (lr);
 }
 
 
diff --git a/src/gns/plugin_gnsrecord_gns.c b/src/gns/plugin_gnsrecord_gns.c
index 5d611e19e..6adad0f34 100644
--- a/src/gns/plugin_gnsrecord_gns.c
+++ b/src/gns/plugin_gnsrecord_gns.c
@@ -140,30 +140,6 @@ gns_value_to_string (void *cls,
       GNUNET_free (ival);
       return box_str;
     }
-  case GNUNET_GNSRECORD_TYPE_REVERSE:
-    {
-      struct GNUNET_GNSRECORD_ReverseRecord rev;
-      char *rev_str;
-      char *pkey_str;
-
-      if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord))
-        return NULL; /* malformed */
-
-      memcpy (&rev,
-              data,
-              sizeof (rev));
-      cdata = data;
-      pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey);
-
-      GNUNET_asprintf (&rev_str,
-                       "%s %s %"SCNu64,
-                       &cdata[sizeof (rev)],
-                       pkey_str,
-                       rev.expiration.abs_value_us);
-      GNUNET_free (pkey_str);
-      return rev_str;
-
-    }
   default:
     return NULL;
   }
@@ -335,48 +311,6 @@ gns_string_to_value (void *cls,
         GNUNET_free (bval);
         return GNUNET_OK;
       }
-    case GNUNET_GNSRECORD_TYPE_REVERSE:
-      {
-        struct GNUNET_GNSRECORD_ReverseRecord *rev;
-        char known_by[253 + 1];
-        struct GNUNET_TIME_Absolute expiration;
-
-        /* TODO: From crypto_ecc.c
-         * Why is this not a constant???
-         */
-        size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
-        if (enclen % 5 > 0)
-          enclen += 5 - enclen % 5;
-        enclen /= 5; /* 260/5 = 52 */
-        char pkey_str[enclen + 1];
-
-        if (3 != SSCANF (s,
-                         "%253s %52s %"SCNu64,
-                         known_by,
-                         pkey_str,
-                         &expiration.abs_value_us))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      _("Unable to parse REVERSE record string `%s'\n"),
-                      s);
-          return GNUNET_SYSERR;
-        }
-        *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen 
(known_by) + 1;
-        *data = rev = GNUNET_malloc (*data_size);
-        if (GNUNET_OK !=
-            GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
-                                                        strlen (pkey_str),
-                                                        &rev->pkey))
-        {
-          GNUNET_free (rev);
-          return GNUNET_SYSERR;
-        }
-        rev->expiration = expiration;
-        GNUNET_memcpy (&rev[1],
-                       known_by,
-                       strlen (known_by));
-        return GNUNET_OK;
-      }
     default:
       return GNUNET_SYSERR;
   }
@@ -397,7 +331,6 @@ static struct {
   { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
   { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
   { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
-  { "REVERSE", GNUNET_GNSRECORD_TYPE_REVERSE },
   { NULL, UINT32_MAX }
 };
 
diff --git a/src/identity-attribute/Makefile.am 
b/src/identity-attribute/Makefile.am
new file mode 100644
index 000000000..2c73a443e
--- /dev/null
+++ b/src/identity-attribute/Makefile.am
@@ -0,0 +1,44 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIBS = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+  libgnunetidentityattribute.la
+
+libgnunetidentityattribute_la_SOURCES = \
+  identity_attribute.c
+libgnunetidentityattribute_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(GN_LIBINTL)
+libgnunetidentityattribute_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
+  -version-info 0:0:0
+
+
+plugin_LTLIBRARIES = \
+  libgnunet_plugin_identity_attribute_gnuid.la
+
+
+libgnunet_plugin_identity_attribute_gnuid_la_SOURCES = \
+  plugin_identity_attribute_gnuid.c
+libgnunet_plugin_identity_attribute_gnuid_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunet_plugin_identity_attribute_gnuid_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
diff --git a/src/identity-attribute/identity_attribute.c 
b/src/identity-attribute/identity_attribute.c
new file mode 100644
index 000000000..cf50d058e
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.c
@@ -0,0 +1,421 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published
+      by the Free Software Foundation; either version 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+      Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file identity-attribute/identity_attribute.c
+ * @brief helper library to manage identity attributes
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "identity_attribute.h"
+#include "gnunet_identity_attribute_plugin.h"
+
+/**
+ * Handle for a plugin
+ */
+struct Plugin
+{
+  /**
+   * Name of the plugin
+   */
+  char *library_name;
+
+  /**
+   * Plugin API
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
+};
+
+/**
+ * Plugins
+ */
+static struct Plugin **attr_plugins;
+
+/**
+ * Number of plugins
+ */
+static unsigned int num_plugins;
+
+/**
+ * Init canary
+ */
+static int initialized;
+
+/**
+ * Add a plugin
+ */
+static void
+add_plugin (void* cls,
+            const char *library_name,
+            void *lib_ret)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = lib_ret;
+  struct Plugin *plugin;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Loading attribute plugin `%s'\n",
+              library_name);
+  plugin = GNUNET_new (struct Plugin);
+  plugin->api = api;
+  plugin->library_name = GNUNET_strdup (library_name);
+  GNUNET_array_append (attr_plugins, num_plugins, plugin);
+}
+
+/**
+ * Load plugins
+ */
+static void
+init()
+{
+  if (GNUNET_YES == initialized)
+    return;
+  initialized = GNUNET_YES;
+  GNUNET_PLUGIN_load_all ("libgnunet_plugin_identity_attribute_", NULL,
+                          &add_plugin, NULL);
+}
+
+/**
+ * Convert a type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  uint32_t ret;
+  
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
+                                                              typename)))
+      return ret;
+  }
+  return UINT32_MAX;
+}
+
+/**
+ * Convert a type number to the corresponding type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char*
+GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  const char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
+                                                        type)))
+      return ret;
+  }
+  return NULL;
+}
+
+/**
+ * Convert human-readable version of a 'claim' of an attribute to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
+                                           const char *s,
+                                           void **data,
+                                           size_t *data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
+                                                   type,
+                                                   s,
+                                                   data,
+                                                   data_size))
+      return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+/**
+ * Convert the 'claim' of an attribute to a string
+ *
+ * @param type the type of attribute
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
+                                           const void* data,
+                                           size_t data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+
+  init();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = attr_plugins[i];
+    if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
+                                                     type,
+                                                     data,
+                                                     data_size)))
+      return ret;
+  }
+  return NULL;
+}
+
+/**
+ * Create a new attribute.
+ *
+ * @param attr_name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
+GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
+               uint32_t type,
+               const void* data,
+               size_t data_size)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
+  char *write_ptr;
+
+  attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) +
+                        strlen (attr_name) + 1 +
+                        data_size);
+  attr->type = type;
+  attr->data_size = data_size;
+  attr->version = 0;
+  write_ptr = (char*)&attr[1];
+  GNUNET_memcpy (write_ptr,
+                 attr_name,
+                 strlen (attr_name) + 1);
+  attr->name = write_ptr;
+  write_ptr += strlen (attr->name) + 1;
+  GNUNET_memcpy (write_ptr,
+                 data,
+                 data_size);
+  attr->data = write_ptr;
+  return attr;
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  size_t len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+    len += GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
+  return len; 
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+                          char *result)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  size_t len;
+  size_t total_len;
+  char* write_ptr;
+
+  write_ptr = result;
+  total_len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    len = GNUNET_IDENTITY_ATTRIBUTE_serialize (le->claim,
+                               write_ptr);
+    total_len += len;
+    write_ptr += len;
+  }
+  return total_len;
+}
+
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
+GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
+                       size_t data_size)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  size_t attr_len;
+  const char* read_ptr;
+
+  if (data_size < sizeof (struct Attribute))
+    return NULL;
+  
+  attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+  read_ptr = data;
+  while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
+  {
+
+    le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+    le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (read_ptr,
+                                           data_size - (read_ptr - data));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Deserialized attribute %s\n", le->claim->name);
+    GNUNET_CONTAINER_DLL_insert (attrs->list_head,
+                                 attrs->list_tail,
+                                 le);
+    attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (le->claim);
+    read_ptr += attr_len;
+  }
+  return attrs;
+}
+
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
+GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *result_le;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *result;
+  size_t len;
+
+  result = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    result_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+    len = sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim) + 
le->claim->data_size;
+    result_le->claim = GNUNET_malloc (len);
+    GNUNET_memcpy (result_le->claim,
+                   le->claim,
+                   len);
+    result_le->claim->name = (const char*)&result_le->claim[1];
+    GNUNET_CONTAINER_DLL_insert (result->list_head,
+                                 result->list_tail,
+                                 result_le);
+  }
+  return result;
+}
+
+
+void
+GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *tmp_le;
+
+  for (le = attrs->list_head; NULL != le;)
+  {
+    GNUNET_free (le->claim);
+    tmp_le = le;
+    le = le->next;
+    GNUNET_free (tmp_le);
+  }
+  GNUNET_free (attrs);
+
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct 
GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
+{
+  return sizeof (struct Attribute) 
+    + strlen (attr->name)
+    + attr->data_size;
+}
+
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct 
GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
+                     char *result)
+{
+  size_t data_len_ser;
+  size_t name_len;
+  struct Attribute *attr_ser;
+  char* write_ptr;
+
+  attr_ser = (struct Attribute*)result;
+  attr_ser->attribute_type = htons (attr->type);
+  attr_ser->attribute_version = htonl (attr->version);
+  name_len = strlen (attr->name);
+  attr_ser->name_len = htons (name_len);
+  write_ptr = (char*)&attr_ser[1];
+  GNUNET_memcpy (write_ptr, attr->name, name_len);
+  write_ptr += name_len;
+  //TODO plugin-ize
+  //data_len_ser = plugin->serialize_attribute_value (attr,
+  //                                                  &attr_ser[1]);
+  data_len_ser = attr->data_size;
+  GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
+  attr_ser->data_size = htons (data_len_ser);
+
+  return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
+}
+
+struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
+GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
+                       size_t data_size)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
+  struct Attribute *attr_ser;
+  size_t data_len;
+  size_t name_len;
+  char* write_ptr;
+
+  if (data_size < sizeof (struct Attribute))
+    return NULL;
+
+  attr_ser = (struct Attribute*)data;
+  data_len = ntohs (attr_ser->data_size);
+  name_len = ntohs (attr_ser->name_len);
+  attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ATTRIBUTE_Claim)
+                        + data_len + name_len + 1);
+  attr->type = ntohs (attr_ser->attribute_type);
+  attr->version = ntohl (attr_ser->attribute_version);
+  attr->data_size = ntohs (attr_ser->data_size);
+
+  write_ptr =  (char*)&attr[1];
+  GNUNET_memcpy (write_ptr,
+                 &attr_ser[1],
+                 name_len);
+  write_ptr[name_len] = '\0';
+  attr->name = write_ptr;
+
+  write_ptr += name_len + 1;
+  GNUNET_memcpy (write_ptr,
+                 (char*)&attr_ser[1] + name_len,
+                 attr->data_size);
+  attr->data = write_ptr;
+  return attr;
+
+}
+
+/* end of identity_attribute.c */
diff --git a/src/identity-attribute/identity_attribute.h 
b/src/identity-attribute/identity_attribute.h
new file mode 100644
index 000000000..8dfc17521
--- /dev/null
+++ b/src/identity-attribute/identity_attribute.h
@@ -0,0 +1,56 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file identity-attribute/identity_attribute.h
+ * @brief GNUnet Identity attributes
+ *
+ */
+#ifndef IDENTITY_ATTRIBUTE_H
+#define IDENTITY_ATTRIBUTE_H
+
+#include "gnunet_identity_provider_service.h"
+
+struct Attribute
+{
+  /**
+   * Attribute type
+   */
+  uint32_t attribute_type;
+
+  /**
+   * Attribute version
+   */
+  uint32_t attribute_version;
+  
+  /**
+   * Name length
+   */
+  uint32_t name_len;
+  
+  /**
+   * Data size
+   */
+  uint32_t data_size;
+
+  //followed by data_size Attribute value data
+};
+
+#endif
diff --git a/src/identity-attribute/plugin_identity_attribute_gnuid.c 
b/src/identity-attribute/plugin_identity_attribute_gnuid.c
new file mode 100644
index 000000000..006b45ea2
--- /dev/null
+++ b/src/identity-attribute/plugin_identity_attribute_gnuid.c
@@ -0,0 +1,184 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2013, 2014, 2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file identity-attribute/plugin_identity_attribute_gnuid.c
+ * @brief identity attribute plugin to provide the API for fundamental 
+ *                 attribute types.
+ *
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_identity_attribute_plugin.h"
+#include <inttypes.h>
+
+
+/**
+ * Convert the 'value' of an attribute to a string.
+ *
+ * @param cls closure, unused
+ * @param type type of the attribute
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+static char *
+gnuid_value_to_string (void *cls,
+                     uint32_t type,
+                     const void *data,
+                     size_t data_size)
+{
+
+  switch (type)
+  {
+  case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
+    return GNUNET_strndup (data, data_size);
+  default:
+    return NULL;
+  }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of an attribute to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the attribute
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+gnuid_string_to_value (void *cls,
+                     uint32_t type,
+                     const char *s,
+                     void **data,
+                     size_t *data_size)
+{
+  if (NULL == s)
+    return GNUNET_SYSERR;
+  switch (type)
+  {
+
+    case GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING:
+      *data = GNUNET_strdup (s);
+      *data_size = strlen (s);
+      return GNUNET_OK;
+    default:
+      return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Mapping of attribute type numbers to human-readable
+ * attribute type names.
+ */
+static struct {
+  const char *name;
+  uint32_t number;
+} gnuid_name_map[] = {
+  { "STRING",  GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING },
+  { NULL, UINT32_MAX }
+};
+
+
+/**
+ * Convert a type name to the corresponding number.
+ *
+ * @param cls closure, unused
+ * @param gnuid_typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+static uint32_t
+gnuid_typename_to_number (void *cls,
+                        const char *gnuid_typename)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (NULL != gnuid_name_map[i].name) &&
+          (0 != strcasecmp (gnuid_typename,
+                            gnuid_name_map[i].name)) )
+    i++;
+  return gnuid_name_map[i].number;
+}
+
+
+/**
+ * Convert a type number (i.e. 1) to the corresponding type string
+ *
+ * @param cls closure, unused
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+static const char *
+gnuid_number_to_typename (void *cls,
+                        uint32_t type)
+{
+  unsigned int i;
+
+  i=0;
+  while ( (NULL != gnuid_name_map[i].name) &&
+          (type != gnuid_name_map[i].number) )
+    i++;
+  return gnuid_name_map[i].name;
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls NULL
+ * @return the exported block API
+ */
+void *
+libgnunet_plugin_identity_attribute_gnuid_init (void *cls)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api;
+
+  api = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions);
+  api->value_to_string = &gnuid_value_to_string;
+  api->string_to_value = &gnuid_string_to_value;
+  api->typename_to_number = &gnuid_typename_to_number;
+  api->number_to_typename = &gnuid_number_to_typename;
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the return value from #libgnunet_plugin_block_test_init()
+ * @return NULL
+ */
+void *
+libgnunet_plugin_identity_attribute_gnuid_done (void *cls)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions *api = cls;
+
+  GNUNET_free (api);
+  return NULL;
+}
+
+/* end of plugin_identity_attribute_type_gnuid.c */
diff --git a/src/identity-provider/Makefile.am 
b/src/identity-provider/Makefile.am
index 0d8752c4c..adf6af3b3 100644
--- a/src/identity-provider/Makefile.am
+++ b/src/identity-provider/Makefile.am
@@ -12,6 +12,15 @@ if USE_COVERAGE
   XLIB = -lgcov
 endif
 
+if HAVE_SQLITE
+SQLITE_PLUGIN = libgnunet_plugin_identity_provider_sqlite.la
+endif
+
+EXTRA_DIST = \
+  test_idp_defaults.conf \
+       test_idp.conf \
+       $(check_SCRIPTS)
+
 pkgcfgdir= $(pkgdatadir)/config.d/
 
 libexecdir= $(pkglibdir)/libexec/
@@ -22,29 +31,51 @@ pkgcfg_DATA = \
 lib_LTLIBRARIES = \
   libgnunetidentityprovider.la
 plugin_LTLIBRARIES = \
-       libgnunet_plugin_rest_identity_provider.la
+       libgnunet_plugin_rest_identity_provider.la \
+  libgnunet_plugin_gnsrecord_identity_provider.la \
+       $(SQLITE_PLUGIN)
 
 bin_PROGRAMS = \
- gnunet-identity-token
+ gnunet-idp
 
 libexec_PROGRAMS = \
  gnunet-service-identity-provider
 
-EXTRA_DIST = \
-  $(pkgcfg_DATA)
+libgnunet_plugin_gnsrecord_identity_provider_la_SOURCES = \
+  plugin_gnsrecord_identity_provider.c
+libgnunet_plugin_gnsrecord_identity_provider_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_identity_provider_sqlite_la_SOURCES = \
+  plugin_identity_provider_sqlite.c
+libgnunet_plugin_identity_provider_sqlite_la_LIBADD = \
+  libgnunetidentityprovider.la  \
+  $(top_builddir)/src/sq/libgnunetsq.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
+  $(LTLIBINTL)
+libgnunet_plugin_identity_provider_sqlite_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
 
 gnunet_service_identity_provider_SOURCES = \
- gnunet-service-identity-provider.c \
- identity_token.c identity_token.h
+ gnunet-service-identity-provider.c
 gnunet_service_identity_provider_LDADD = \
  $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
  $(top_builddir)/src/util/libgnunetutil.la \
  $(top_builddir)/src/namestore/libgnunetnamestore.la \
  $(top_builddir)/src/identity/libgnunetidentity.la \
  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/abe/libgnunetabe.la \
+ $(top_builddir)/src/credential/libgnunetcredential.la \
+ $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
+ libgnunetidentityprovider.la \
  $(top_builddir)/src/gns/libgnunetgns.la \
- $(GN_LIBINTL) \
- -ljansson
+ $(GN_LIBINTL)
 
 libgnunetidentityprovider_la_SOURCES = \
  identity_provider_api.c \
@@ -57,22 +88,37 @@ libgnunetidentityprovider_la_LDFLAGS = \
        -version-info 0:0:0
 
 libgnunet_plugin_rest_identity_provider_la_SOURCES = \
-  plugin_rest_identity_provider.c
+  plugin_rest_identity_provider.c \
+       jwt.c
 libgnunet_plugin_rest_identity_provider_la_LIBADD = \
        $(top_builddir)/src/identity/libgnunetidentity.la \
        libgnunetidentityprovider.la \
        $(top_builddir)/src/rest/libgnunetrest.la \
        $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+       $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
        $(top_builddir)/src/namestore/libgnunetnamestore.la \
   $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
   $(LTLIBINTL) -ljansson -lmicrohttpd
 libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
 
-
-gnunet_identity_token_SOURCES = \
- gnunet-identity-token.c
-gnunet_identity_token_LDADD = \
+gnunet_idp_SOURCES = \
+ gnunet-idp.c
+gnunet_idp_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
-  -ljansson -lmicrohttpd \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+       libgnunetidentityprovider.la \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+       $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \
   $(GN_LIBINTL)
+
+check_SCRIPTS = \
+       test_idp_attribute.sh \
+       test_idp_issue.sh \
+       test_idp_consume.sh \
+  test_idp_revoke.sh
+
+if ENABLE_TEST_RUN
+ AM_TESTS_ENVIRONMENT=export 
GNUNET_PREFIX=$${GNUNET_PREFIX:address@hidden@};export 
PATH=$${GNUNET_PREFIX:address@hidden@}/bin:$$PATH;unset XDG_DATA_HOME;unset 
XDG_CONFIG_HOME;
+ TESTS = $(check_SCRIPTS)
+endif
diff --git a/src/identity-provider/gnunet-identity-token.c 
b/src/identity-provider/gnunet-identity-token.c
deleted file mode 100644
index 30b63bfc4..000000000
--- a/src/identity-provider/gnunet-identity-token.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published
-   by the Free Software Foundation; either version 3, or (at your
-   option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GNUnet; see the file COPYING.  If not, write to the
-   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.
-   */
-/**
- * @author Martin Schanzenbach
- * @file src/identity-provider/gnunet-service-identity-provider.c
- * @brief Identity Token Service
- *
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include <jansson.h>
-#include "gnunet_signatures.h"
-
-/**
- * The token
- */
-static char* token;
-
-/**
- * Weather to print the token
- */
-static int print_token;
-
-static void
-run (void *cls,
-     char *const *args,
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  char *payload;
-  char *header;
-  //Get token parts
-  const char *header_b64;
-  const char *payload_b64;
-  const char *signature_b32;
-  const char *keystring;
-  char *data;
-  json_t *payload_json;
-  json_t *keystring_json;
-  json_error_t error;
-  struct GNUNET_CRYPTO_EcdsaPublicKey key;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  struct GNUNET_CRYPTO_EcdsaSignature sig;
-
-  if (NULL == token)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                _("Option `-t' is required\n"));
-    return;
-  }
-  header_b64 = strtok (token, ".");
-  payload_b64 = strtok (NULL, ".");
-  signature_b32 = strtok (NULL, ".");
-  if ( (NULL == header_b64) ||
-       (NULL == payload_b64) ||
-       (NULL == signature_b32) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                _("Token `%s' is malformed\n"),
-                token);
-    GNUNET_free (token);
-    token = NULL;
-    return;
-  }
-
-  //Decode payload
-  GNUNET_STRINGS_base64_decode (payload_b64,
-                                strlen (payload_b64),
-                                &payload);
-  //Decode header
-  GNUNET_STRINGS_base64_decode (header_b64,
-                                strlen (header_b64),
-                                &header);
-
-
-  GNUNET_asprintf(&data,
-                  "%s,%s",
-                  header_b64,
-                  payload_b64);
-  char *val = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) 
+ strlen (data));
-  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose*)val;
-  purpose->size = htonl(sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
strlen (data));
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
-  GNUNET_memcpy (&purpose[1], data, strlen(data));
-  GNUNET_free (data);
-  GNUNET_free (token);
-  token = NULL;
-
-  if (print_token)
-    printf ("Token:\nHeader:\t\t%s\nPayload:\t%s\n",
-            header,
-            payload);
-  GNUNET_free (header);
-
-  payload_json = json_loads (payload, 0, &error);
-  GNUNET_free (payload);
-
-  if ((NULL == payload_json) || (! json_is_object (payload_json)) )
-  {
-    GNUNET_free (val);
-    return;
-  }
-  keystring_json =  json_object_get (payload_json, "iss");
-  if (! json_is_string (keystring_json))
-  {
-    GNUNET_free (val);
-    return;
-  }
-  keystring = json_string_value (keystring_json);
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_ecdsa_public_key_from_string (keystring,
-                                                  strlen (keystring),
-                                                  &key))
-  {
-    GNUNET_free (val);
-    return;
-  }
-  GNUNET_STRINGS_string_to_data (signature_b32,
-                                 strlen (signature_b32),
-                                 &sig,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
-
-  if (print_token)
-    printf ("Signature:\t%s\n",
-            keystring);
-
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN,
-                                 purpose,
-                                 &sig,
-                                 &key))
-    printf("Signature not OK!\n");
-  else
-    printf("Signature OK!\n");
-  GNUNET_free (val);
-  return;
-}
-
-
-int
-main(int argc, char *const argv[])
-{
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-
-    GNUNET_GETOPT_option_string ('t',
-                                 "token",
-                                 NULL,
-                                 gettext_noop ("GNUid token"),
-                                 &token),
-
-    GNUNET_GETOPT_option_flag ('p',
-                                  "print",
-                                  gettext_noop ("Print token contents"),
-                                  &print_token),
-
-    GNUNET_GETOPT_OPTION_END
-  };
-  return GNUNET_PROGRAM_run (argc, argv, "ct",
-                             "ct", options,
-                             &run, NULL);
-}
diff --git a/src/identity-provider/gnunet-idp.c 
b/src/identity-provider/gnunet-idp.c
new file mode 100644
index 000000000..62f07842b
--- /dev/null
+++ b/src/identity-provider/gnunet-idp.c
@@ -0,0 +1,439 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file src/identity-provider/gnunet-idp.c
+ * @brief Identity Provider utility
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_identity_provider_service.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_signatures.h"
+
+/**
+ * return value
+ */
+static int ret;
+
+/**
+ * List attribute flag
+ */
+static int list;
+
+/**
+ * Relying party
+ */
+static char* rp;
+
+/**
+ * The attribute
+ */
+static char* attr_name;
+
+/**
+ * Attribute value
+ */
+static char* attr_value;
+
+/**
+ * Attributes to issue
+ */
+static char* issue_attrs;
+
+/**
+ * Ticket to consume
+ */
+static char* consume_ticket;
+
+/**
+ * Attribute type
+ */
+static char* type_str;
+
+/**
+ * Ticket to revoke
+ */
+static char* revoke_ticket;
+
+/**
+ * Ego name
+ */
+static char* ego_name;
+
+/**
+ * Identity handle
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+/**
+ * IdP handle
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
+
+/**
+ * IdP operation
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
+
+/**
+ * Attribute iterator
+ */
+static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
+
+/**
+ * Master ABE key
+ */
+static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+
+/**
+ * ego private key
+ */
+static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
+
+/**
+ * rp public key
+ */
+static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
+
+/**
+ * Ticket to consume
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+
+/**
+ * Attribute list
+ */
+static struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list;
+
+static void
+do_cleanup(void *cls)
+{
+  if (NULL != attr_iterator)
+    GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
+  if (NULL != idp_handle)
+    GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  if (NULL != abe_key)
+    GNUNET_free (abe_key);
+  if (NULL != attr_list)
+    GNUNET_free (attr_list);
+}
+
+static void
+ticket_issue_cb (void* cls,
+                 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+{
+  char* ticket_str;
+  if (NULL != ticket) {
+    ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
+                                                      sizeof (struct 
GNUNET_IDENTITY_PROVIDER_Ticket));
+    printf("%s\n",
+           ticket_str);
+    GNUNET_free (ticket_str);
+  }
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+store_attr_cont (void *cls,
+                 int32_t success,
+                 const char*emsg)
+{
+  if (GNUNET_SYSERR == success) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "%s\n", emsg);
+  }
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+process_attrs (void *cls,
+         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+         const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
+{
+  char *value_str;
+  if (NULL == identity)
+  {
+    GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+    return;
+  }
+  if (NULL == attr)
+  {
+    ret = 1;
+    return;
+  }
+  value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type,
+                                                     attr->data,
+                                                     attr->data_size);
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "%s: %s\n", attr->name, value_str);
+}
+
+
+static void
+iter_error (void *cls)
+{
+  attr_iterator = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed to iterate over attributes\n");
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+process_rvk (void *cls, int success, const char* msg)
+{
+  if (GNUNET_OK != success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "Revocation failed.\n");
+    ret = 1;
+  }
+  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+}
+
+static void
+iter_finished (void *cls)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
+  char *data;
+  size_t data_size;
+  int type;
+
+  attr_iterator = NULL;
+  if (list)
+  {
+    GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
+    return;
+  }
+
+  if (issue_attrs)
+  {
+    idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle,
+                                                    pkey,
+                                                    &rp_key,
+                                                    attr_list,
+                                                    &ticket_issue_cb,
+                                                    NULL);
+    return;
+  }
+  if (consume_ticket)
+  {
+    idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle,
+                                                      pkey,
+                                                      &ticket,
+                                                      &process_attrs,
+                                                      NULL);
+    return;
+  }
+  if (revoke_ticket)
+  {
+    idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle,
+                                                     pkey,
+                                                     &ticket,
+                                                     &process_rvk,
+                                                     NULL);
+    return;
+  }
+  if (NULL == type_str)
+    type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING;
+  else
+    type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str);
+
+  GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value 
(type,
+                                             attr_value,
+                                             (void**)&data,
+                                             &data_size));
+  claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name,
+                                               type,
+                                               data,
+                                               data_size);
+  idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
+                                                     pkey,
+                                                     claim,
+                                                     &store_attr_cont,
+                                                     NULL);
+
+
+}
+
+static void
+iter_cb (void *cls,
+         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+         const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  char *attrs_tmp;
+  char *attr_str;
+
+  if (issue_attrs)
+  {
+    attrs_tmp = GNUNET_strdup (issue_attrs);
+    attr_str = strtok (attrs_tmp, ",");
+    while (NULL != attr_str) {
+      if (0 != strcmp (attr_str, attr->name)) {
+        attr_str = strtok (NULL, ",");
+        continue;
+      }
+      le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+      le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name,
+                                                       attr->type,
+                                                       attr->data,
+                                                       attr->data_size);
+      GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
+                                   attr_list->list_tail,
+                                   le);
+      break;
+    }
+    GNUNET_free (attrs_tmp);
+  } else if (list) {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "%s: %s\n", attr->name, (char*)attr->data);
+  }
+  GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
+}
+
+static void
+ego_cb (void *cls,
+        struct GNUNET_IDENTITY_Ego *ego,
+        void **ctx,
+        const char *name)
+{
+  if (NULL == name)
+    return;
+  if (0 != strcmp (name, ego_name))
+    return;
+  pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+
+  if (NULL != rp)
+    GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
+                                                strlen (rp),
+                                                &rp_key);
+  if (NULL != consume_ticket)
+    GNUNET_STRINGS_string_to_data (consume_ticket,
+                                   strlen (consume_ticket),
+                                   &ticket,
+                                   sizeof (struct 
GNUNET_IDENTITY_PROVIDER_Ticket));
+  if (NULL != revoke_ticket)
+    GNUNET_STRINGS_string_to_data (revoke_ticket,
+                                   strlen (revoke_ticket),
+                                   &ticket,
+                                   sizeof (struct 
GNUNET_IDENTITY_PROVIDER_Ticket));
+
+
+  attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+
+  attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
+                                                                 pkey,
+                                                                 &iter_error,
+                                                                 NULL,
+                                                                 &iter_cb,
+                                                                 NULL,
+                                                                 
&iter_finished,
+                                                                 NULL);
+
+
+}
+
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  ret = 0;
+  if (NULL == ego_name)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                _("Ego is required\n"));
+    return;
+  } 
+
+  idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
+  //Get Ego
+  identity_handle = GNUNET_IDENTITY_connect (c,
+                                             &ego_cb,
+                                             NULL);
+
+
+}
+
+
+int
+main(int argc, char *const argv[])
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+
+    GNUNET_GETOPT_option_string ('a',
+                                 "add",
+                                 NULL,
+                                 gettext_noop ("Add attribute"),
+                                 &attr_name),
+
+    GNUNET_GETOPT_option_string ('V',
+                                 "value",
+                                 NULL,
+                                 gettext_noop ("Attribute value"),
+                                 &attr_value),
+    GNUNET_GETOPT_option_string ('e',
+                                 "ego",
+                                 NULL,
+                                 gettext_noop ("Ego"),
+                                 &ego_name),
+    GNUNET_GETOPT_option_string ('r',
+                                 "rp",
+                                 NULL,
+                                 gettext_noop ("Audience (relying party)"),
+                                 &rp),
+    GNUNET_GETOPT_option_flag ('D',
+                               "dump",
+                               gettext_noop ("List attributes for Ego"),
+                               &list),
+    GNUNET_GETOPT_option_string ('i',
+                                 "issue",
+                                 NULL,
+                                 gettext_noop ("Issue a ticket"),
+                                 &issue_attrs),
+    GNUNET_GETOPT_option_string ('C',
+                                 "consume",
+                                 NULL,
+                                 gettext_noop ("Consume a ticket"),
+                                 &consume_ticket),
+    GNUNET_GETOPT_option_string ('R',
+                                 "revoke",
+                                 NULL,
+                                 gettext_noop ("Revoke a ticket"),
+                                 &revoke_ticket),
+    GNUNET_GETOPT_option_string ('t',
+                                 "type",
+                                 NULL,
+                                 gettext_noop ("Type of attribute"),
+                                 &type_str),
+    GNUNET_GETOPT_OPTION_END
+  };
+  GNUNET_PROGRAM_run (argc, argv, "ct",
+                      "ct", options,
+                      &run, NULL);
+  return ret;
+}
diff --git a/src/identity-provider/gnunet-service-identity-provider.c 
b/src/identity-provider/gnunet-service-identity-provider.c
index 53fd02c9f..4e1de36cd 100644
--- a/src/identity-provider/gnunet-service-identity-provider.c
+++ b/src/identity-provider/gnunet-service-identity-provider.c
@@ -30,12 +30,14 @@
 #include "gnunet_identity_service.h"
 #include "gnunet_gnsrecord_lib.h"
 #include "gnunet_namestore_service.h"
+#include "gnunet_abe_lib.h"
+#include "gnunet_credential_service.h"
 #include "gnunet_statistics_service.h"
 #include "gnunet_gns_service.h"
+#include "gnunet_identity_provider_plugin.h"
+#include "gnunet_identity_attribute_lib.h"
 #include "gnunet_signatures.h"
 #include "identity_provider.h"
-#include "identity_token.h"
-#include <inttypes.h>
 
 /**
  * First pass state
@@ -58,24 +60,19 @@
 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
 
 /**
- * Service state (to detect initial update pass)
- */
-static int state;
-
-/**
- * Head of ego entry DLL
+ * Identity handle
  */
-static struct EgoEntry *ego_head;
+static struct GNUNET_IDENTITY_Handle *identity_handle;
 
 /**
- * Tail of ego entry DLL
+ * Database handle
  */
-static struct EgoEntry *ego_tail;
+static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
 
 /**
- * Identity handle
+ * Name of DB plugin
  */
-static struct GNUNET_IDENTITY_Handle *identity_handle;
+static char *db_lib_name;
 
 /**
  * Token expiration interval
@@ -93,6 +90,16 @@ static struct GNUNET_NAMESTORE_Handle *ns_handle;
 static struct GNUNET_GNS_Handle *gns_handle;
 
 /**
+ * Credential handle
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
+/**
+ * Stats handle
+ */
+static struct GNUNET_STATISTICS_Handle *stats_handle;
+
+/**
  * Namestore qe
  */
 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
@@ -112,11 +119,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task;
  */
 static struct GNUNET_SCHEDULER_Task *update_task;
 
-/**
- * Timeout for next update pass
- */
-static struct GNUNET_TIME_Relative min_rel_exp;
-
 
 /**
  * Currently processed token
@@ -134,122 +136,227 @@ static char* label;
 static char* scopes;
 
 /**
- * Expiration for processed token
+ * Handle to the statistics service.
  */
-static uint64_t rd_exp;
+static struct GNUNET_STATISTICS_Handle *stats;
 
 /**
- * ECDHE Privkey for processed token metadata
+ * Our configuration.
  */
-static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey;
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 /**
- * Handle to the statistics service.
+ * An idp client
  */
-static struct GNUNET_STATISTICS_Handle *stats;
+struct IdpClient;
 
 /**
- * Our configuration.
+ * A ticket iteration operation.
  */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
+struct TicketIteration
+{
+  /**
+   * DLL
+   */
+  struct TicketIteration *next;
+
+  /**
+   * DLL
+   */
+  struct TicketIteration *prev;
 
+  /**
+   * Client which intiated this zone iteration
+   */
+  struct IdpClient *client;
+
+  /**
+   * Key of the identity we are iterating over.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /**
+   * Identity is audience
+   */
+  uint32_t is_audience;
+
+  /**
+   * The operation id fot the iteration in the response for the client
+   */
+  uint32_t r_id;
+
+  /**
+   * Offset of the iteration used to address next result of the 
+   * iteration in the store
+   *
+   * Initialy set to 0 in handle_iteration_start
+   * Incremented with by every call to handle_iteration_next
+   */
+  uint32_t offset;
+
+};
+
+
+
+/**
+ * Callback after an ABE bootstrap
+ *
+ * @param cls closure
+ * @param abe_key the ABE key that exists or was created
+ */
+typedef void
+(*AbeBootstrapResult) (void *cls,
+                       struct GNUNET_ABE_AbeMasterKey *abe_key);
 
-struct ExchangeHandle
+
+struct AbeBootstrapHandle
 {
+  /**
+   * Function to call when finished
+   */
+  AbeBootstrapResult proc;
 
   /**
-   * Client connection
+   * Callback closure
    */
-  struct GNUNET_SERVICE_Client *client;
+  char *proc_cls;
 
   /**
-   * Ticket
+   * Key of the zone we are iterating over.
    */
-  struct TokenTicket *ticket;
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
   /**
-   * Token returned
+   * Namestore Queue Entry
    */
-  struct IdentityToken *token;
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
 
   /**
-   * LookupRequest
+   * The issuer egos ABE master key
    */
-  struct GNUNET_GNS_LookupRequest *lookup_request;
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+};
 
+/**
+ * An attribute iteration operation.
+ */
+struct AttributeIterator
+{
   /**
-   * Audience Key
+   * Next element in the DLL
    */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
+  struct AttributeIterator *next;
 
   /**
-   * Label to return
+   * Previous element in the DLL
    */
-  char *label;
+  struct AttributeIterator *prev;
 
   /**
-   * request id
+   * IDP client which intiated this zone iteration
    */
-  uint32_t r_id;
+  struct IdpClient *client;
+
+  /**
+   * Key of the zone we are iterating over.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * The issuer egos ABE master key
+   */
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+  /**
+   * Namestore iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+  /**
+   * The operation id fot the zone iteration in the response for the client
+   */
+  uint32_t request_id;
+
 };
 
-struct IssueHandle
+
+
+/**
+ * An idp client
+ */
+struct IdpClient
 {
 
   /**
-   * Client connection
+   * The client
    */
   struct GNUNET_SERVICE_Client *client;
 
   /**
-   * Issuer Key
+   * Message queue for transmission to @e client
+   */
+  struct GNUNET_MQ_Handle *mq;
+  
+  /**
+   * Head of the DLL of
+   * Attribute iteration operations in 
+   * progress initiated by this client
    */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
+  struct AttributeIterator *op_head;
 
   /**
-   * Issue pubkey
+   * Tail of the DLL of
+   * Attribute iteration operations 
+   * in progress initiated by this client
    */
-  struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
+  struct AttributeIterator *op_tail;
 
   /**
-   * Audience Key
+   * Head of DLL of ticket iteration ops
    */
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+  struct TicketIteration *ticket_iter_head;
 
   /**
-   * Expiration
+   * Tail of DLL of ticket iteration ops
    */
-  struct GNUNET_TIME_Absolute expiration;
+  struct TicketIteration *ticket_iter_tail;
+
 
   /**
-   * Scopes
+   * Head of DLL of ticket revocation ops
    */
-  char *scopes;
+  struct TicketRevocationHandle *revocation_list_head;
 
   /**
-   * nonce
+   * Tail of DLL of ticket revocation ops
    */
-  uint64_t nonce;
+  struct TicketRevocationHandle *revocation_list_tail;
+};
+
+
+
+struct AttributeStoreHandle
+{
 
   /**
-   * NS iterator
+   * Client connection
    */
-  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+  struct IdpClient *client;
 
   /**
-   * Attribute map
+   * Identity
    */
-  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
   /**
-   * Token
+   * Identity pubkey
    */
-  struct IdentityToken *token;
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
 
   /**
-   * Ticket
+   * The issuer egos ABE master key
    */
-  struct TokenTicket *ticket;
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
 
   /**
    * QueueEntry
@@ -257,9 +364,9 @@ struct IssueHandle
   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
 
   /**
-   * The label the token is stored under
+   * The attribute to store
    */
-  char *label;
+  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
 
   /**
    * request id
@@ -267,1329 +374,2000 @@ struct IssueHandle
   uint32_t r_id;
 };
 
-/**
- * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t 
format
- *
- */
-struct EgoEntry
+
+/* Prototype */
+struct ParallelLookup;
+
+struct ConsumeTicketHandle
 {
+
   /**
-   * DLL
+   * Client connection
    */
-  struct EgoEntry *next;
+  struct IdpClient *client;
 
   /**
-   * DLL
+   * Ticket
    */
-  struct EgoEntry *prev;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
 
   /**
-   * Ego handle
+   * LookupRequest
    */
-  struct GNUNET_IDENTITY_Ego *ego;
+  struct GNUNET_GNS_LookupRequest *lookup_request;
 
   /**
-   * Attribute map. Contains the attributes as json_t
+   * Audience Key
    */
-  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
   /**
-   * Attributes are old and should be updated if GNUNET_YES
+   * Audience Key
    */
-  int attributes_dirty;
-};
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
 
-/**
- * Continuation for token store call
- *
- * @param cls NULL
- * @param success error code
- * @param emsg error message
- */
-static void
-store_token_cont (void *cls,
-                  int32_t success,
-                  const char *emsg)
-{
-  ns_qe = NULL;
-  if (GNUNET_SYSERR == success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to update token: %s\n",
-                emsg);
-    return;
-  }
-  GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-}
+  /**
+   * Lookup DLL
+   */
+  struct ParallelLookup *parallel_lookups_head;
+
+  /**
+   * Lookup DLL
+   */
+  struct ParallelLookup *parallel_lookups_tail;
+  
+  /**
+   * Kill task
+   */
+  struct GNUNET_SCHEDULER_Task *kill_task;
+
+  /**
+   * The ABE key
+   */
+  struct GNUNET_ABE_AbeKey *key;
 
+  /**
+   * Attributes
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+  
+  /**
+   * Lookup time
+   */
+  struct GNUNET_TIME_Absolute lookup_start_time;
+ 
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
 
 /**
- * This function updates the old token with new attributes,
- * removes deleted attributes and expiration times.
- *
- * @param cls the ego entry
+ * Handle for a parallel GNS lookup job
  */
-static void
-handle_token_update (void *cls)
+struct ParallelLookup
 {
-  char *token_metadata;
-  char *write_ptr;
-  char *enc_token_str;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey;
-  struct EgoEntry *ego_entry = cls;
-  struct GNUNET_GNSRECORD_Data token_record[2];
-  struct GNUNET_HashCode key_hash;
-  struct GNUNET_TIME_Relative token_rel_exp;
-  struct GNUNET_TIME_Relative token_ttl;
-  struct GNUNET_TIME_Absolute token_exp;
-  struct GNUNET_TIME_Absolute token_nbf;
-  struct GNUNET_TIME_Absolute new_exp;
-  struct GNUNET_TIME_Absolute new_iat;
-  struct GNUNET_TIME_Absolute new_nbf;
-  struct IdentityToken *new_token;
-  struct TokenAttr *cur_value;
-  struct TokenAttr *attr;
-  size_t token_metadata_len;
-
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                      &pub_key);
-
-  //Note: We need the token expiration time here. Not the record expiration
-  //time.
-  //There are two types of tokens: Token that expire on GNS level with
-  //an absolute expiration time. Those are basically tokens that will
-  //be automatically revoked on (record)expiration.
-  //Tokens stored with relative expiration times will expire on the token 
level (token expiration)
-  //but this service will reissue new tokens that can be retrieved from GNS
-  //automatically.
-
-  for (attr = token->attr_head; NULL != attr; attr = attr->next)
-  {
-    if (0 == strcmp (attr->name, "exp"))
-    {
-      GNUNET_assert (1 == sscanf (attr->val_head->value,
-              "%"SCNu64,
-              &token_exp.abs_value_us));
-    } else if (0 == strcmp (attr->name, "nbf")) {
-      GNUNET_assert (1 == sscanf (attr->val_head->value,
-              "%"SCNu64,
-              &token_nbf.abs_value_us));
-    }
-  }
-  token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
+  /* DLL */
+  struct ParallelLookup *next;
 
-  token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
-  if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
-  {
-    //This token is not yet expired! Save and skip
-    if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
-    {
-      min_rel_exp = token_ttl;
-    }
-    GNUNET_free (token);
-    token = NULL;
-    GNUNET_free (label);
-    label = NULL;
-    GNUNET_free (scopes);
-    scopes = NULL;
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Token is expired. Create a new one\n");
-  new_token = token_create (&pub_key,
-                            &token->aud_key);
-  new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
-  new_nbf = GNUNET_TIME_absolute_get ();
-  new_iat = new_nbf;
-  for (attr = token->attr_head; NULL != attr; attr = attr->next)
-  {
-    if (0 == strcmp (attr->name, "exp"))
-    {
-      token_add_attr_int (new_token, attr->name, new_exp.abs_value_us);
-    }
-    else if (0 == strcmp (attr->name, "nbf"))
-    {
-      token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us);
-    }
-    else if (0 == strcmp (attr->name, "iat"))
-    {
-      token_add_attr_int (new_token, attr->name, new_iat.abs_value_us);
-    }
-    else if ((0 == strcmp (attr->name, "iss"))
-             || (0 == strcmp (attr->name, "aud")))
-    {
-      //Omit
-    }
-    else if (0 == strcmp (attr->name, "sub"))
-    {
-      token_add_attr (new_token,
-                      attr->name,
-                      attr->val_head->value);
-    }
-    else
-    {
-      GNUNET_CRYPTO_hash (attr->name,
-                          strlen (attr->name),
-                          &key_hash);
-      //Check if attr still exists. omit of not
-      if (GNUNET_NO !=
-          GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
-                                                  &key_hash))
-      {
-        cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
-                                                       &key_hash);
-        GNUNET_assert (NULL != cur_value);
-        GNUNET_CONTAINER_DLL_insert (new_token->attr_head,
-                                     new_token->attr_tail,
-                                     cur_value);
-      }
-    }
-  }
+  /* DLL */
+  struct ParallelLookup *prev;
 
-  // reassemble and set
-  GNUNET_assert (token_serialize (new_token,
-                                  priv_key,
-                                  &new_ecdhe_privkey,
-                                  &enc_token_str));
-
-  token_record[0].data = enc_token_str;
-  token_record[0].data_size = strlen (enc_token_str) + 1;
-  token_record[0].expiration_time = rd_exp; //Old expiration time
-  token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
-  token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
-
-  //Meta
-  token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
-    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
-    + strlen (scopes) + 1; //With 0-Terminator
-  token_metadata = GNUNET_malloc (token_metadata_len);
-  write_ptr = token_metadata;
-  GNUNET_memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct 
GNUNET_CRYPTO_EcdhePrivateKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
-  GNUNET_memcpy (write_ptr, &token->aud_key, sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-  GNUNET_memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
-
-  token_record[1].data = token_metadata;
-  token_record[1].data_size = token_metadata_len;
-  token_record[1].expiration_time = rd_exp;
-  token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
-  token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
-
-  ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                          priv_key,
-                                          label,
-                                          2,
-                                          token_record,
-                                          &store_token_cont,
-                                          ego_entry);
-  token_destroy (new_token);
-  token_destroy (token);
-  GNUNET_free (new_ecdhe_privkey);
-  GNUNET_free (enc_token_str);
-  token = NULL;
-  GNUNET_free (label);
-  label = NULL;
-  GNUNET_free (scopes);
-  scopes = NULL;
-}
+  /* The GNS request */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
 
+  /* The handle the return to */
+  struct ConsumeTicketHandle *handle;
 
-static void
-update_identities(void *cls);
+  /**
+   * Lookup time
+   */
+  struct GNUNET_TIME_Absolute lookup_start_time;
 
+  /* The label to look up */
+  char *label;
+};
 
 /**
- *
- * Cleanup attr_map
- *
- * @param cls NULL
- * @param key the key
- * @param value the json_t attribute value
- * @return #GNUNET_YES
+ * Ticket revocation request handle
  */
-static int
-clear_ego_attrs (void *cls,
-                 const struct GNUNET_HashCode *key,
-                 void *value)
-{
-  struct TokenAttr *attr = value;
-  struct TokenAttrValue *val;
-  struct TokenAttrValue *tmp_val;
-  for (val = attr->val_head; NULL != val;)
-  {
-    tmp_val = val->next;
-    GNUNET_CONTAINER_DLL_remove (attr->val_head,
-                                 attr->val_tail,
-                                 val);
-    GNUNET_free (val->value);
-    GNUNET_free (val);
-    val = tmp_val;
-  }
-  GNUNET_free (attr->name);
-  GNUNET_free (attr);
+struct TicketRevocationHandle
+{
+  /**
+   * DLL
+   */
+  struct TicketRevocationHandle *next;
 
-  return GNUNET_YES;
-}
+  /**
+   * DLL
+   */
+  struct TicketRevocationHandle *prev;
 
+  /**
+   * Client connection
+   */
+  struct IdpClient *client;
 
-static void
-token_collect_error_cb (void *cls)
-{
-  struct EgoEntry *ego_entry = cls;
+  /**
+   * Attributes to reissue
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              ">>> Updating Ego failed!\n");
-  //Clear attribute map for ego
-  GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
-                                         &clear_ego_attrs,
-                                         ego_entry);
-  GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
-  update_task = GNUNET_SCHEDULER_add_now (&update_identities,
-                                          ego_entry->next);
+  /**
+   * Attributes to revoke
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
 
-}
+  /**
+   * Issuer Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
+  /**
+   * Ticket to issue
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
 
-static void
-token_collect_finished_cb (void *cls)
-{
-  struct EgoEntry *ego_entry = cls;
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * Namestore iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+  /**
+   * The ABE master key
+   */
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+  /**
+   * Offset
+   */
+  uint32_t offset;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              ">>> Updating Ego finished\n");
-  //Clear attribute map for ego
-  GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
-                                         &clear_ego_attrs,
-                                         ego_entry);
-  GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
-  update_task = GNUNET_SCHEDULER_add_now (&update_identities,
-                                          ego_entry->next);
-}
 
 
 /**
- *
- * Update all ID_TOKEN records for an identity and store them
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
+ * Ticket issue request handle
+ */
+struct TicketIssueHandle
+{
+
+  /**
+   * Client connection
+   */
+  struct IdpClient *client;
+
+  /**
+   * Attributes to issue
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+
+  /**
+   * Issuer Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Ticket to issue
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
+
+
+/**
+ * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t 
format
+ *
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego handle
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+
+  /**
+   * Attribute map. Contains the attributes as json_t
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *attr_map;
+
+};
+
+/**
+ * Cleanup task
  */
 static void
-token_collect (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *lbl,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct EgoEntry *ego_entry = cls;
-  const struct GNUNET_GNSRECORD_Data *token_record;
-  const struct GNUNET_GNSRECORD_Data *token_metadata_record;
-  struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key;
-
-  //There should be only a single record for a token under a label
-  if (2 != rd_count)
+cleanup()
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != stats)
   {
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
+    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
+    stats = NULL;
   }
+  GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
+                                              TKT_database)); 
+  GNUNET_free (db_lib_name);
+  db_lib_name = NULL;
+  if (NULL != timeout_task)
+    GNUNET_SCHEDULER_cancel (timeout_task);
+  if (NULL != update_task)
+    GNUNET_SCHEDULER_cancel (update_task);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  if (NULL != gns_handle)
+    GNUNET_GNS_disconnect (gns_handle);
+  if (NULL != credential_handle)
+    GNUNET_CREDENTIAL_disconnect (credential_handle);
+  if (NULL != ns_it)
+    GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
+  if (NULL != ns_qe)
+    GNUNET_NAMESTORE_cancel (ns_qe);
+  if (NULL != ns_handle)
+    GNUNET_NAMESTORE_disconnect (ns_handle);
+  if (NULL != stats_handle)
+    GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
+  GNUNET_free_non_null (token);
+  GNUNET_free_non_null (label);
+
+}
 
-  if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
+/**
+ * Shutdown task
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Shutting down...\n");
+  cleanup();
+}
+
+/**
+ * Finished storing newly bootstrapped ABE key
+ */
+static void
+bootstrap_store_cont (void *cls,
+                      int32_t success,
+                      const char *emsg)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  if (GNUNET_SYSERR == success)
   {
-    token_metadata_record = &rd[0];
-    token_record = &rd[1];
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to bootstrap ABE master %s\n",
+                emsg);
+    abh->proc (abh->proc_cls, NULL);
+    GNUNET_free (abh->abe_key);
+    GNUNET_free (abh);
+    return;
+  }
+  abh->proc (abh->proc_cls, abh->abe_key);
+  GNUNET_free (abh);
+}
+
+/**
+ * Generates and stores a new ABE key
+ */
+static void
+bootstrap_store_task (void *cls)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+  char *key;
+
+  rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
+                                                              (void**)&key);
+  rd[0].data = key;
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
+  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | 
GNUNET_GNSRECORD_RF_PRIVATE;
+  rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+  abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                               &abh->identity,
+                                               "+",
+                                               1,
+                                               rd,
+                                               &bootstrap_store_cont,
+                                               abh);
+  GNUNET_free (key);
+}
+
+/**
+ * Error checking for ABE master
+ */
+static void
+bootstrap_abe_error (void *cls)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  GNUNET_free (abh);
+  abh->proc (abh->proc_cls, NULL);
+  GNUNET_free (abh);
+}
+
+
+/**
+ * Handle ABE lookup in namestore
+ */
+static void
+bootstrap_abe_result (void *cls,
+                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                      const char *label,
+                      unsigned int rd_count,
+                      const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  struct GNUNET_ABE_AbeMasterKey *abe_key;
+
+  for (uint32_t i=0;i<rd_count;i++) {
+    if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
+      continue;
+    abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
+                                                          rd[i].data_size);
+    abh->proc (abh->proc_cls, abe_key);
+    GNUNET_free (abh);
+    return;
   }
-  else
+
+  //No ABE master found, bootstrapping...
+  abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
+  GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
+}
+
+/**
+ * Bootstrap ABE master if it does not yet exists.
+ * Will call the AbeBootstrapResult processor when done.
+ * will always recreate the ABE key of GNUNET_YES == recreate
+ */
+static void
+bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+               AbeBootstrapResult proc,
+               void* cls,
+               int recreate)
+{
+  struct AbeBootstrapHandle *abh;
+
+  abh = GNUNET_new (struct AbeBootstrapHandle);
+  abh->proc = proc;
+  abh->proc_cls = cls;
+  abh->identity = *identity;
+  if (GNUNET_YES == recreate)
   {
-    token_record = &rd[0];
-    token_metadata_record = &rd[1];
+    abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
+    GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
+  } else {
+    abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
+                                                  identity,
+                                                  "+",
+                                                  &bootstrap_abe_error,
+                                                  abh,
+                                                  &bootstrap_abe_result,
+                                                  abh);
   }
-  if (token_metadata_record->record_type != 
GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
+}
+
+
+
+static int
+create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
+                         struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
+                         struct GNUNET_CRYPTO_SymmetricInitializationVector 
*iv)
+{
+  struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
+
+  GNUNET_CRYPTO_hash_to_enc (new_key_hash,
+                             &new_key_hash_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", 
(char*)&new_key_hash_str);
+  static const char ctx_key[] = "gnuid-aes-ctx-key";
+  GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
+                     new_key_hash, sizeof (struct GNUNET_HashCode),
+                     ctx_key, strlen (ctx_key),
+                     NULL, 0);
+  static const char ctx_iv[] = "gnuid-aes-ctx-iv";
+  GNUNET_CRYPTO_kdf (iv, sizeof (struct 
GNUNET_CRYPTO_SymmetricInitializationVector),
+                     new_key_hash, sizeof (struct GNUNET_HashCode),
+                     ctx_iv, strlen (ctx_iv),
+                     NULL, 0);
+  return GNUNET_OK;
+}
+
+static void
+cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
+{
+  if (NULL != handle->attrs)
+    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
+  if (NULL != handle->ns_qe)
+    GNUNET_NAMESTORE_cancel (handle->ns_qe);
+  GNUNET_free (handle);
+}
+
+
+static void
+send_ticket_result (struct IdpClient *client,
+                    uint32_t r_id,
+                    const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                    const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+  struct TicketResultMessage *irm;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
+
+  /* store ticket in DB */
+  if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
+                                               ticket,
+                                               attrs))
   {
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to store ticket after issue\n");
+    GNUNET_break (0);
   }
-  if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
+
+  env = GNUNET_MQ_msg_extra (irm,
+                             sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
+                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
+  ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
+  *ticket_buf = *ticket;
+  irm->id = htonl (r_id);
+  GNUNET_MQ_send (client->mq,
+                  env);
+}
+
+static void
+store_ticket_issue_cont (void *cls,
+                         int32_t success,
+                         const char *emsg)
+{
+  struct TicketIssueHandle *handle = cls;
+
+  handle->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
   {
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+    cleanup_ticket_issue_handle (handle);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+                "Unknown Error\n");
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
+  send_ticket_result (handle->client,
+                      handle->r_id,
+                      &handle->ticket,
+                      handle->attrs);
+  cleanup_ticket_issue_handle (handle);
+}
+
 
-  //Get metadata and decrypt token
-  priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey 
*)token_metadata_record->data;
-  ecdhe_privkey = *priv_key;
-  aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1];
-  scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
 
-  token_parse2 (token_record->data,
-                &ecdhe_privkey,
-                aud_key,
-                &token);
+int
+serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                        const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList 
*attrs,
+                        const struct GNUNET_ABE_AbeKey *rp_key,
+                        struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
+                        char **result)
+{
+  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  char *enc_keyinfo;
+  char *serialized_key;
+  char *buf;
+  char *write_ptr;
+  char attrs_str_len;
+  ssize_t size;
+
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct GNUNET_HashCode new_key_hash;
+  ssize_t enc_size;
+
+  size = GNUNET_ABE_cpabe_serialize_key (rp_key,
+                                            (void**)&serialized_key);
+  attrs_str_len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next) {
+    attrs_str_len += strlen (le->claim->name) + 1;
+  }
+  buf = GNUNET_malloc (attrs_str_len + size);
+  write_ptr = buf;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Writing attributes\n");
+  for (le = attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "%s\n", le->claim->name);
 
-  label = GNUNET_strdup (lbl);
-  rd_exp = token_record->expiration_time;
 
-  GNUNET_SCHEDULER_add_now (&handle_token_update,
-                            ego_entry);
+    GNUNET_memcpy (write_ptr,
+                   le->claim->name,
+                   strlen (le->claim->name));
+    write_ptr[strlen (le->claim->name)] = ',';
+    write_ptr += strlen (le->claim->name) + 1;
+  }
+  write_ptr--;
+  write_ptr[0] = '\0'; //replace last , with a 0-terminator
+  write_ptr++;
+  GNUNET_memcpy (write_ptr,
+                 serialized_key,
+                 size);
+  GNUNET_free (serialized_key);
+  // ECDH keypair E = eG
+  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
+  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
+                                      &ecdh_pubkey);
+  enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
+  // Derived key K = H(eB)
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
+                                                        &ticket->audience,
+                                                        &new_key_hash));
+  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
+  enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
+                                              size + attrs_str_len,
+                                              &skey, &iv,
+                                              enc_keyinfo);
+  *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
+                           enc_size);
+  GNUNET_memcpy (*result,
+                 &ecdh_pubkey,
+                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+                 enc_keyinfo,
+                 enc_size);
+  GNUNET_free (enc_keyinfo);
+  GNUNET_free (buf);
+  return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
 }
 
 
+
 static void
-attribute_collect_error_cb (void *cls)
+issue_ticket_after_abe_bootstrap (void *cls,
+                                  struct GNUNET_ABE_AbeMasterKey *abe_key)
 {
-  struct EgoEntry *ego_entry = cls;
+  struct TicketIssueHandle *ih = cls;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+  struct GNUNET_GNSRECORD_Data code_record[1];
+  struct GNUNET_ABE_AbeKey *rp_key;
+  char *code_record_data;
+  char **attrs;
+  char *label;
+  char *policy;
+  int attrs_len;
+  uint32_t i;
+  size_t code_record_len;
+
+  //Create new ABE key for RP
+  attrs_len = 0;
+  for (le = ih->attrs->list_head; NULL != le; le = le->next)
+    attrs_len++;
+  attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
+  i = 0;
+  for (le = ih->attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_asprintf (&policy, "%s_%lu",
+                     le->claim->name,
+                     le->claim->version);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Adding attribute to key: %s\n",
+                policy);
+    attrs[i] = policy;
+    i++;
+  }
+  attrs[i] = NULL;
+  rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
+                                           attrs);
+
+  //TODO review this wireformat
+  code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
+                                            ih->attrs,
+                                            rp_key,
+                                            &ecdhe_privkey,
+                                            &code_record_data);
+  code_record[0].data = code_record_data;
+  code_record[0].data_size = code_record_len;
+  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
+  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+
+  label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
+                                               sizeof (uint64_t));
+  //Publish record
+  ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                              &ih->identity,
+                                              label,
+                                              1,
+                                              code_record,
+                                              &store_ticket_issue_cont,
+                                              ih);
+  //for (; i > 0; i--)
+  //  GNUNET_free (attrs[i-1]);
+  GNUNET_free (ecdhe_privkey);
+  GNUNET_free (label);
+  GNUNET_free (attrs);
+  GNUNET_free (code_record_data);
+  GNUNET_ABE_cpabe_delete_key (rp_key,
+                                  GNUNET_YES);
+  GNUNET_ABE_cpabe_delete_master_key (abe_key);
+}
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              ">>> Updating Attributes failed!\n");
-  ego_entry->attributes_dirty = GNUNET_NO;
-  update_task = GNUNET_SCHEDULER_add_now (&update_identities,
-                                          ego_entry);
+
+static int
+check_issue_ticket_message(void *cls,
+                           const struct IssueTicketMessage *im)
+{
+  uint16_t size;
+
+  size = ntohs (im->header.size);
+  if (size <= sizeof (struct IssueTicketMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
 }
 
 
 static void
-attribute_collect_finished_cb (void *cls)
+handle_issue_ticket_message (void *cls,
+                             const struct IssueTicketMessage *im)
 {
-  struct EgoEntry *ego_entry = cls;
+  struct TicketIssueHandle *ih;
+  struct IdpClient *idp = cls;
+  size_t attrs_len;
+
+  ih = GNUNET_new (struct TicketIssueHandle);
+  attrs_len = ntohs (im->attr_len);
+  ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], 
attrs_len);
+  ih->r_id = ntohl (im->id);
+  ih->client = idp;
+  ih->identity = im->identity;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
+                                      &ih->ticket.identity);
+  ih->ticket.audience = im->rp;
+  ih->ticket.rnd =
+    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
+                              UINT64_MAX);
+  bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, 
GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              ">>> Updating Attributes finished\n");
-  ego_entry->attributes_dirty = GNUNET_NO;
-  update_task = GNUNET_SCHEDULER_add_now (&update_identities,
-                                          ego_entry);
 }
 
+/**********************************************************
+ * Revocation
+ **********************************************************/
 
 /**
+ * Cleanup revoke handle
  *
- * Collect all ID_ATTR records for an identity and store them
+ * @param rh the ticket revocation handle
+ */
+static void
+cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
+{
+  if (NULL != rh->attrs)
+    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->attrs);
+  if (NULL != rh->rvk_attrs)
+    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->rvk_attrs);
+  if (NULL != rh->abe_key)
+    GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
+  if (NULL != rh->ns_qe)
+    GNUNET_NAMESTORE_cancel (rh->ns_qe);
+  if (NULL != rh->ns_it)
+    GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
+  GNUNET_free (rh);
+}
+
+
+/**
+ * Send revocation result
  *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
+ * @param rh ticket revocation handle
+ * @param success GNUNET_OK if successful result
+ */
+static void
+send_revocation_finished (struct TicketRevocationHandle *rh,
+                          uint32_t success)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct RevokeTicketResultMessage *trm;
+
+  env = GNUNET_MQ_msg (trm,
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
+  trm->id = htonl (rh->r_id);
+  trm->success = htonl (success);
+  GNUNET_MQ_send (rh->client->mq,
+                  env);
+  GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
+                               rh->client->revocation_list_tail,
+                               rh);
+}
+
+
+/**
+ * Process ticket from database
  *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
  */
 static void
-attribute_collect (void *cls,
-                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                   const char *lbl,
-                   unsigned int rd_count,
-                   const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct EgoEntry *ego_entry = cls;
-  struct GNUNET_HashCode key;
-  struct TokenAttr *attr;
-  struct TokenAttrValue *val;
-  char *val_str;
-  int i;
-
-  if (0 == rd_count)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
-  }
-  GNUNET_CRYPTO_hash (lbl,
-                      strlen (lbl),
-                      &key);
-  if (1 == rd_count)
-  {
-    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      val_str = GNUNET_GNSRECORD_value_to_string (rd->record_type,
-                                                  rd->data,
-                                                  rd->data_size);
-      attr = GNUNET_malloc (sizeof (struct TokenAttr));
-      attr->name = GNUNET_strdup (lbl);
-      val = GNUNET_malloc (sizeof (struct TokenAttrValue));
-      val->value = val_str;
-      GNUNET_CONTAINER_DLL_insert (attr->val_head,
-                                   attr->val_tail,
-                                   val);
-      GNUNET_assert (GNUNET_OK ==
-                     GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
-                                                        &key,
-                                                        attr,
-                                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-    }
+ticket_reissue_proc (void *cls,
+                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                     const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
+
+static void
+revocation_reissue_tickets (struct TicketRevocationHandle *rh);
 
-    GNUNET_NAMESTORE_zone_iterator_next (ns_it);
-    return;
-  }
 
-  attr = GNUNET_malloc (sizeof (struct TokenAttr));
-  attr->name = GNUNET_strdup (lbl);
-  for (i = 0; i < rd_count; i++)
+static void reissue_next (void *cls)
+{
+  struct TicketRevocationHandle *rh = cls;
+  revocation_reissue_tickets (rh);
+}
+
+
+static void
+reissue_ticket_cont (void *cls,
+                     int32_t success,
+                     const char *emsg)
+{
+  struct TicketRevocationHandle *rh = cls;
+
+  rh->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
   {
-    if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
-                                                  rd[i].data,
-                                                  rd[i].data_size);
-      val = GNUNET_malloc (sizeof (struct TokenAttrValue));
-      val->value = val_str;
-      GNUNET_CONTAINER_DLL_insert (attr->val_head,
-                                   attr->val_tail,
-                                   val);
-    }
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+                "Unknown Error\n");
+    send_revocation_finished (rh, GNUNET_SYSERR);
+    cleanup_revoke_ticket_handle (rh);
+    return;
   }
-  GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put 
(ego_entry->attr_map,
-                                                                 &key,
-                                                                 attr,
-                                                                 
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  GNUNET_NAMESTORE_zone_iterator_next (ns_it);
+  rh->offset++;
+  GNUNET_SCHEDULER_add_now (&reissue_next, rh);
 }
 
+
 /**
+ * Process ticket from database
  *
- * Update identity information for ego. If attribute map is
- * dirty, first update the attributes.
- *
- * @param cls the ego to update
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
  */
 static void
-update_identities(void *cls)
+ticket_reissue_proc (void *cls,
+                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                     const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
 {
-  struct EgoEntry *next_ego = cls;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct TicketRevocationHandle *rh = cls;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+  struct GNUNET_GNSRECORD_Data code_record[1];
+  struct GNUNET_ABE_AbeKey *rp_key;
+  char *code_record_data;
+  char **attr_arr;
+  char *label;
+  char *policy;
+  int attrs_len;
+  uint32_t i;
+  int reissue_ticket;
+  size_t code_record_len;
+
 
-  update_task = NULL;
-  if (NULL == next_ego)
+  if (NULL == ticket)
   {
-    if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
-      min_rel_exp = MIN_WAIT_TIME;
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                ">>> Finished. Rescheduling in %"SCNu64"\n",
-                min_rel_exp.rel_value_us);
-    ns_it = NULL;
-    //finished -> reschedule
-    update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp,
-                                                &update_identities,
-                                                ego_head);
-    min_rel_exp.rel_value_us = 0;
+                "Iteration done\n");
     return;
   }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
-  if (GNUNET_YES == next_ego->attributes_dirty)
+
+  if (0 == memcmp (&ticket->audience,
+                   &rh->ticket.audience,
+                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
   {
-    //Starting over. We must update the Attributes for they might have changed.
-    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                   priv_key,
-                                                   &attribute_collect_error_cb,
-                                                   next_ego,
-                                                   &attribute_collect,
-                                                   next_ego,
-                                                   
&attribute_collect_finished_cb,
-                                                   next_ego);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Do not reissue for this identity.!\n");
 
+    rh->offset++;
+    GNUNET_SCHEDULER_add_now (&reissue_next, rh);
+    return;
   }
-  else
+
+  /* 
+   * Check if any attribute of this ticket intersects with a rollover attribute
+   */
+  reissue_ticket = GNUNET_NO;
+  for (le = attrs->list_head; NULL != le; le = le->next)
   {
-    //Ego will be dirty next time
-    next_ego->attributes_dirty = GNUNET_YES;
-    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                   priv_key,
-                                                   &token_collect_error_cb,
-                                                   next_ego,
-                                                   &token_collect,
-                                                   next_ego,
-                                                   &token_collect_finished_cb,
-                                                   next_ego);
+    for (le_rollover = rh->rvk_attrs->list_head;
+         NULL != le_rollover;
+         le_rollover = le_rollover->next)
+    {
+      if (0 == strcmp (le_rollover->claim->name,
+                       le->claim->name))
+      {
+        reissue_ticket = GNUNET_YES;
+        le->claim->version = le_rollover->claim->version;
+      }
+    }
   }
+
+  if (GNUNET_NO == reissue_ticket)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Skipping ticket.\n");
+
+    rh->offset++;
+    GNUNET_SCHEDULER_add_now (&reissue_next, rh);
+
+
+    return;
+  }
+
+  //Create new ABE key for RP
+  attrs_len = 0;
+
+  /* If this is the RP we want to revoke attributes of, the do so */
+
+  for (le = attrs->list_head; NULL != le; le = le->next)
+    attrs_len++;
+  attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
+  i = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_asprintf (&policy, "%s_%lu",
+                     le->claim->name,
+                     le->claim->version);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Recreating key with %s\n", policy);
+    attr_arr[i] = policy;
+    i++;
+  }
+  attr_arr[i] = NULL;
+  rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
+                                           attr_arr);
+
+  //TODO review this wireformat
+  code_record_len = serialize_abe_keyinfo2 (ticket,
+                                            attrs,
+                                            rp_key,
+                                            &ecdhe_privkey,
+                                            &code_record_data);
+  code_record[0].data = code_record_data;
+  code_record[0].data_size = code_record_len;
+  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
+  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+
+  label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                               sizeof (uint64_t));
+  //Publish record
+  rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                              &rh->identity,
+                                              label,
+                                              1,
+                                              code_record,
+                                              &reissue_ticket_cont,
+                                              rh);
+  //for (; i > 0; i--)
+  //  GNUNET_free (attr_arr[i-1]);
+  GNUNET_free (ecdhe_privkey);
+  GNUNET_free (label);
+  GNUNET_free (attr_arr);
+  GNUNET_free (code_record_data);
+  GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
 }
 
 
+/* Prototype for below function */
+static void
+attr_reenc_cont (void *cls,
+                 int32_t success,
+                 const char *emsg);
+
+static void
+revocation_reissue_tickets (struct TicketRevocationHandle *rh)
+{
+  int ret;
+  /* Done, issue new keys */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Revocation Phase III: Reissuing Tickets\n");
+  if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
+                                                             
&rh->ticket.identity,
+                                                             GNUNET_NO,
+                                                             rh->offset,
+                                                             
&ticket_reissue_proc,
+                                                             rh)))
+  {
+    GNUNET_break (0);
+  }
+  if (GNUNET_NO == ret)
+  {
+    send_revocation_finished (rh, GNUNET_OK);
+    cleanup_revoke_ticket_handle (rh);
+    return;
+  }
+}
+
 /**
- * Function called initially to start update task
+ * Revoke next attribte by reencryption with
+ * new ABE master
  */
 static void
-init_cont ()
+reenc_next_attribute (struct TicketRevocationHandle *rh)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n");
-  //Initially iterate all itenties and refresh all tokens
-  update_task = GNUNET_SCHEDULER_add_now (&update_identities,
-                                          ego_head);
+  struct GNUNET_GNSRECORD_Data rd[1];
+  char* buf;
+  char* enc_buf;
+  size_t enc_size;
+  char* rd_buf;
+  size_t buf_size;
+  char* policy;
+  uint32_t attr_ver;
+
+  if (NULL == rh->attrs->list_head)
+  {
+    revocation_reissue_tickets (rh);
+    return;
+  }
+  buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size 
(rh->attrs->list_head->claim);
+  buf = GNUNET_malloc (buf_size);
+  GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
+                       buf);
+  rh->attrs->list_head->claim->version++;
+  GNUNET_asprintf (&policy, "%s_%lu",
+                   rh->attrs->list_head->claim->name,
+                   rh->attrs->list_head->claim->version);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Encrypting with policy %s\n", policy);
+  /**
+   * Encrypt the attribute value and store in namestore
+   */
+  enc_size = GNUNET_ABE_cpabe_encrypt (buf,
+                                          buf_size,
+                                          policy, //Policy
+                                          rh->abe_key,
+                                          (void**)&enc_buf);
+  GNUNET_free (buf);
+  GNUNET_free (policy);
+  rd[0].data_size = enc_size + sizeof (uint32_t);
+  rd_buf = GNUNET_malloc (rd[0].data_size);
+  attr_ver = htonl (rh->attrs->list_head->claim->version);
+  GNUNET_memcpy (rd_buf,
+                 &attr_ver,
+                 sizeof (uint32_t));
+  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+                 enc_buf,
+                 enc_size);
+  rd[0].data = rd_buf;
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
+  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+  rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+  rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                              &rh->identity,
+                                              
rh->attrs->list_head->claim->name,
+                                              1,
+                                              rd,
+                                              &attr_reenc_cont,
+                                              rh);
+  GNUNET_free (enc_buf);
+  GNUNET_free (rd_buf);
 }
 
-
 /**
- * Initial ego collection function.
- *
- * @param cls NULL
- * @param ego ego
- * @param ctx context
- * @param identifier ego name
+ * Namestore callback after revoked attribute
+ * is stored
  */
 static void
-list_ego (void *cls,
-          struct GNUNET_IDENTITY_Ego *ego,
-          void **ctx,
-          const char *identifier)
+attr_reenc_cont (void *cls,
+                 int32_t success,
+                 const char *emsg)
 {
-  struct EgoEntry *new_entry;
-  if ((NULL == ego) && (STATE_INIT == state))
+  struct TicketRevocationHandle *rh = cls;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+
+  if (GNUNET_SYSERR == success)
   {
-    state = STATE_POST_INIT;
-    init_cont ();
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to reencrypt attribute %s\n",
+                emsg);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
-  if (STATE_INIT == state) {
-    new_entry = GNUNET_malloc (sizeof (struct EgoEntry));
-    new_entry->ego = ego;
-    new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
-                                                                GNUNET_NO);
-    new_entry->attributes_dirty = GNUNET_YES;
-    GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
+  if (NULL == rh->attrs->list_head)
+  {
+    revocation_reissue_tickets (rh);
+    return;
   }
+  le = rh->attrs->list_head;
+  GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
+                               rh->attrs->list_tail,
+                               le);
+  GNUNET_assert (NULL != rh->rvk_attrs);
+  GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
+                               rh->rvk_attrs->list_tail,
+                               le);
+
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Re-encrypting next attribute\n");
+  reenc_next_attribute (rh);
 }
 
-/**
- * Cleanup task
- */
+
 static void
-cleanup()
+process_attributes_to_update (void *cls,
+                              const struct GNUNET_IDENTITY_PROVIDER_Ticket 
*ticket,
+                              const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList 
*attrs)
 {
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
+  struct TicketRevocationHandle *rh = cls;
 
+  rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != stats)
+              "Revocation Phase I: Collecting attributes\n");
+  /* Reencrypt all attributes with new key */
+  if (NULL == rh->attrs->list_head)
   {
-    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
-    stats = NULL;
+    /* No attributes to reencrypt */
+    send_revocation_finished (rh, GNUNET_OK);
+    cleanup_revoke_ticket_handle (rh);
+    return;
+  } else {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Revocation Phase II: Re-encrypting attributes\n");
+    reenc_next_attribute (rh);
   }
 
-  if (NULL != timeout_task)
-    GNUNET_SCHEDULER_cancel (timeout_task);
-  if (NULL != update_task)
-    GNUNET_SCHEDULER_cancel (update_task);
-  if (NULL != identity_handle)
-    GNUNET_IDENTITY_disconnect (identity_handle);
-  if (NULL != gns_handle)
-    GNUNET_GNS_disconnect (gns_handle);
-  if (NULL != ns_it)
-    GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
-  if (NULL != ns_qe)
-    GNUNET_NAMESTORE_cancel (ns_qe);
-  if (NULL != ns_handle)
-    GNUNET_NAMESTORE_disconnect (ns_handle);
-  if (NULL != token)
-    GNUNET_free (token);
-  if (NULL != label)
-    GNUNET_free (label);
+}
+
 
-  for (ego_entry = ego_head;
-       NULL != ego_entry;)
+
+static void
+get_ticket_after_abe_bootstrap (void *cls,
+                                struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finished ABE bootstrap\n");
+  struct TicketRevocationHandle *rh = cls;
+  rh->abe_key = abe_key;
+  TKT_database->get_ticket_attributes (TKT_database->cls,
+                                       &rh->ticket,
+                                       &process_attributes_to_update,
+                                       rh);
+}
+
+static int
+check_revoke_ticket_message(void *cls,
+                            const struct RevokeTicketMessage *im)
+{
+  uint16_t size;
+
+  size = ntohs (im->header.size);
+  if (size <= sizeof (struct RevokeTicketMessage))
   {
-    ego_tmp = ego_entry;
-    if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
-    {
-      GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
-                                             &clear_ego_attrs,
-                                             ego_tmp);
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
 
-    }
-    GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map);
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp);
+static void
+handle_revoke_ticket_message (void *cls,
+                              const struct RevokeTicketMessage *rm)
+{
+  struct TicketRevocationHandle *rh;
+  struct IdpClient *idp = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
+
+  rh = GNUNET_new (struct TicketRevocationHandle);
+  ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
+  rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+  rh->ticket = *ticket;
+  rh->r_id = ntohl (rm->id);
+  rh->client = idp;
+  rh->identity = rm->identity;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
+                                      &rh->ticket.identity);
+  GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
+                               idp->revocation_list_tail,
+                               rh);
+  bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, 
GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
+
+}
+
+
+static void
+cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
+{
+  if (NULL != handle->key)
+    GNUNET_ABE_cpabe_delete_key (handle->key,
+                                    GNUNET_YES);
+  if (NULL != handle->attrs)
+    GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
+  GNUNET_free (handle);
+}
+
+
+
+static int
+check_consume_ticket_message(void *cls,
+                             const struct ConsumeTicketMessage *cm)
+{
+  uint16_t size;
+
+  size = ntohs (cm->header.size);
+  if (size <= sizeof (struct ConsumeTicketMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
   }
+  return GNUNET_OK;
 }
 
-/**
- * Shutdown task
- *
- * @param cls NULL
- * @param tc task context
- */
 static void
-do_shutdown (void *cls)
+process_parallel_lookup2 (void *cls, uint32_t rd_count,
+                          const struct GNUNET_GNSRECORD_Data *rd)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Shutting down...\n");
-  cleanup();
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Parallel lookup finished (count=%u)\n", rd_count);
+  struct ParallelLookup *parallel_lookup = cls;
+  struct ConsumeTicketHandle *handle = parallel_lookup->handle;
+  struct ConsumeTicketResultMessage *crm;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
+  struct GNUNET_TIME_Absolute decrypt_duration;
+  char *data;
+  char *data_tmp;
+  ssize_t attr_len;
+  size_t attrs_len;
+
+  GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
+                               handle->parallel_lookups_tail,
+                               parallel_lookup);
+  GNUNET_free (parallel_lookup->label);
+
+  GNUNET_STATISTICS_update (stats_handle,
+                            "attribute_lookup_time_total",
+                            GNUNET_TIME_absolute_get_duration 
(parallel_lookup->lookup_start_time).rel_value_us,
+                            GNUNET_YES);
+  GNUNET_STATISTICS_update (stats_handle,
+                            "attribute_lookups_count",
+                            1,
+                            GNUNET_YES);
+
+
+  GNUNET_free (parallel_lookup);
+  if (1 != rd_count)
+    GNUNET_break(0);//TODO
+  if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
+  {
+    decrypt_duration = GNUNET_TIME_absolute_get ();
+    attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
+                                            rd->data_size - sizeof (uint32_t),
+                                            handle->key,
+                                            (void**)&data);
+    if (GNUNET_SYSERR != attr_len) 
+    {
+      GNUNET_STATISTICS_update (stats_handle,
+                                "abe_decrypt_time_total",
+                                GNUNET_TIME_absolute_get_duration 
(decrypt_duration).rel_value_us,
+                                GNUNET_YES);
+      GNUNET_STATISTICS_update (stats_handle,
+                                "abe_decrypt_count",
+                                1,
+                                GNUNET_YES);
+
+      attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
+      attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
+                                                  attr_len);
+      attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
+      GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
+                                   handle->attrs->list_tail,
+                                   attr_le);
+      GNUNET_free (data);
+    }
+  }
+  if (NULL != handle->parallel_lookups_head)
+    return; //Wait for more
+  /* Else we are done */
+
+  /* Store ticket in DB */
+  if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
+                                               &handle->ticket,
+                                               handle->attrs))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to store ticket after consume\n");
+    GNUNET_break (0);
+  }
+
+  GNUNET_SCHEDULER_cancel (handle->kill_task);
+  attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size 
(handle->attrs);
+  env = GNUNET_MQ_msg_extra (crm,
+                             attrs_len,
+                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
+  crm->id = htonl (handle->r_id);
+  crm->attrs_len = htons (attrs_len);
+  crm->identity = handle->ticket.identity;
+  data_tmp = (char *) &crm[1];
+  GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
+                            data_tmp);
+  GNUNET_MQ_send (handle->client->mq, env);
+  cleanup_consume_ticket_handle (handle);
+}
+
+void
+abort_parallel_lookups2 (void *cls)
+{
+  struct ConsumeTicketHandle *handle = cls;
+  struct ParallelLookup *lu;
+  struct ParallelLookup *tmp;
+  struct AttributeResultMessage *arm;
+  struct GNUNET_MQ_Envelope *env;
+
+  for (lu = handle->parallel_lookups_head;
+       NULL != lu;) {
+    GNUNET_GNS_lookup_cancel (lu->lookup_request);
+    GNUNET_free (lu->label);
+    tmp = lu->next;
+    GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
+                                 handle->parallel_lookups_tail,
+                                 lu);
+    GNUNET_free (lu);
+    lu = tmp;
+  }
+  env = GNUNET_MQ_msg (arm,
+                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+  arm->id = htonl (handle->r_id);
+  arm->attr_len = htons (0);
+  GNUNET_MQ_send (handle->client->mq, env);
+
 }
 
 
-static struct GNUNET_MQ_Envelope*
-create_exchange_result_message (const char* token,
-                                const char* label,
-                                uint64_t ticket_nonce,
-                                uint64_t id)
-{
-  struct GNUNET_MQ_Envelope *env;
-  struct ExchangeResultMessage *erm;
-  uint16_t token_len = strlen (token) + 1;
-
-  env = GNUNET_MQ_msg_extra (erm,
-                             token_len,
-                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
-  erm->ticket_nonce = htonl (ticket_nonce);
-  erm->id = id;
-  GNUNET_memcpy (&erm[1], token, token_len);
-  return env;
+static void
+process_consume_abe_key (void *cls, uint32_t rd_count,
+                         const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct ConsumeTicketHandle *handle = cls;
+  struct GNUNET_HashCode new_key_hash;
+  struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
+  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
+  struct ParallelLookup *parallel_lookup;
+  size_t size;
+  char *buf;
+  char *scope;
+  char *lookup_query;
+
+  handle->lookup_request = NULL;
+  if (1 != rd_count)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Number of keys %d != 1.",
+                rd_count);
+    cleanup_consume_ticket_handle (handle);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+
+  //Decrypt
+  ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
+
+  buf = GNUNET_malloc (rd->data_size - sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey));
+
+  //Calculate symmetric key from ecdh parameters
+  GNUNET_assert (GNUNET_OK == 
+                 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
+                                           ecdh_key,
+                                           &new_key_hash));
+  create_sym_key_from_ecdh (&new_key_hash,
+                            &enc_key,
+                            &enc_iv);
+  size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey),
+                                          rd->data_size - sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey),
+                                          &enc_key,
+                                          &enc_iv,
+                                          buf);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Decrypted bytes: %zd Expected bytes: %zd\n",
+              size, rd->data_size - sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_STATISTICS_update (stats_handle,
+                            "abe_key_lookup_time_total",
+                            GNUNET_TIME_absolute_get_duration 
(handle->lookup_start_time).rel_value_us,
+                            GNUNET_YES);
+  GNUNET_STATISTICS_update (stats_handle,
+                            "abe_key_lookups_count",
+                            1,
+                            GNUNET_YES);
+  scopes = GNUNET_strdup (buf);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Scopes %s\n", scopes);
+  handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen 
(scopes) + 1),
+                                                     rd->data_size - sizeof 
(struct GNUNET_CRYPTO_EcdhePublicKey)
+                                                     - strlen (scopes) - 1);
+
+  for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
+  {
+    GNUNET_asprintf (&lookup_query,
+                     "%s.gnu",
+                     scope);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Looking up %s\n", lookup_query);
+    parallel_lookup = GNUNET_new (struct ParallelLookup);
+    parallel_lookup->handle = handle;
+    parallel_lookup->label = GNUNET_strdup (scope);
+    parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
+    parallel_lookup->lookup_request
+      = GNUNET_GNS_lookup (gns_handle,
+                           lookup_query,
+                           &handle->ticket.identity,
+                           GNUNET_GNSRECORD_TYPE_ID_ATTR,
+                           GNUNET_GNS_LO_DEFAULT,
+                           &process_parallel_lookup2,
+                           parallel_lookup);
+    GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
+                                 handle->parallel_lookups_tail,
+                                 parallel_lookup);
+    GNUNET_free (lookup_query);
+  }
+  GNUNET_free (scopes);
+  GNUNET_free (buf);
+  handle->kill_task = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
+                                                    &abort_parallel_lookups2,
+                                                    handle);
 }
 
 
-static struct GNUNET_MQ_Envelope*
-create_issue_result_message (const char* label,
-                             const char* ticket,
-                             const char* token,
-                             uint64_t id)
+static void
+handle_consume_ticket_message (void *cls,
+                               const struct ConsumeTicketMessage *cm)
 {
-  struct GNUNET_MQ_Envelope *env;
-  struct IssueResultMessage *irm;
-  char *tmp_str;
-  size_t len;
-
-  GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
-  len = strlen (tmp_str) + 1;
-  env = GNUNET_MQ_msg_extra (irm,
-                             len,
-                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
-  irm->id = id;
-  GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
-  GNUNET_free (tmp_str);
-  return env;
+  struct ConsumeTicketHandle *ch;
+  struct IdpClient *idp = cls;
+  char* lookup_query;
+  char* rnd_label;
+
+  ch = GNUNET_new (struct ConsumeTicketHandle);
+  ch->r_id = ntohl (cm->id);
+  ch->client = idp;
+  ch->identity = cm->identity;
+  ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
+  GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
+                                      &ch->identity_pub);
+  ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
+  rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
+                                                   sizeof (uint64_t));
+  GNUNET_asprintf (&lookup_query,
+                   "%s.gnu",
+                   rnd_label);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Looking for ABE key under %s\n", lookup_query);
+  ch->lookup_start_time = GNUNET_TIME_absolute_get ();
+  ch->lookup_request
+    = GNUNET_GNS_lookup (gns_handle,
+                         lookup_query,
+                         &ch->ticket.identity,
+                         GNUNET_GNSRECORD_TYPE_ABE_KEY,
+                         GNUNET_GNS_LO_DEFAULT,
+                         &process_consume_abe_key,
+                         ch);
+  GNUNET_free (rnd_label);
+  GNUNET_free (lookup_query);
+  GNUNET_SERVICE_client_continue (idp->client);
 }
 
 static void
-cleanup_issue_handle (struct IssueHandle *handle)
-{
-  if (NULL != handle->attr_map)
-    GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
-  if (NULL != handle->scopes)
-    GNUNET_free (handle->scopes);
-  if (NULL != handle->token)
-    token_destroy (handle->token);
-  if (NULL != handle->ticket)
-    ticket_destroy (handle->ticket);
-  if (NULL != handle->label)
-    GNUNET_free (handle->label);
+cleanup_as_handle (struct AttributeStoreHandle *handle)
+{
+  if (NULL != handle->claim)
+    GNUNET_free (handle->claim);
+  if (NULL != handle->abe_key)
+    GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
   GNUNET_free (handle);
 }
 
 static void
-store_token_issue_cont (void *cls,
-                        int32_t success,
-                        const char *emsg)
+attr_store_cont (void *cls,
+                 int32_t success,
+                 const char *emsg)
 {
-  struct IssueHandle *handle = cls;
+  struct AttributeStoreHandle *as_handle = cls;
   struct GNUNET_MQ_Envelope *env;
-  char *ticket_str;
-  char *token_str;
+  struct AttributeStoreResultMessage *acr_msg;
 
-  handle->ns_qe = NULL;
   if (GNUNET_SYSERR == success)
   {
-    cleanup_issue_handle (handle);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
-                "Unknown Error\n");
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-    return;
-  }
-  if (GNUNET_OK != ticket_serialize (handle->ticket,
-                                     &handle->iss_key,
-                                     &ticket_str))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
-                "Error serializing ticket\n");
-    cleanup_issue_handle (handle);
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-    return;
-  }
-  if (GNUNET_OK != token_to_string (handle->token,
-                                    &handle->iss_key,
-                                    &token_str))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
-                "Error serializing token\n");
-    GNUNET_free (ticket_str);
-    cleanup_issue_handle (handle);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to store attribute %s\n",
+                emsg);
+    cleanup_as_handle (as_handle);
     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
-  env = create_issue_result_message (handle->label,
-                                     ticket_str,
-                                     token_str,
-                                     handle->r_id);
-  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending ATTRIBUTE_STORE_RESPONSE message\n");
+  env = GNUNET_MQ_msg (acr_msg,
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
+  acr_msg->id = htonl (as_handle->r_id);
+  acr_msg->op_result = htonl (GNUNET_OK);
+  GNUNET_MQ_send (as_handle->client->mq,
                   env);
-  cleanup_issue_handle (handle);
-  GNUNET_free (ticket_str);
-  GNUNET_free (token_str);
+  cleanup_as_handle (as_handle);
 }
 
-
-/**
- * Build a token and store it
- *
- * @param cls the IssueHandle
- */
 static void
-sign_and_return_token (void *cls)
+attr_store_task (void *cls)
 {
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-  struct IssueHandle *handle = cls;
-  struct GNUNET_GNSRECORD_Data token_record[2];
-  char *nonce_str;
-  char *enc_token_str;
-  char *token_metadata;
-  char* write_ptr;
-  uint64_t time;
-  uint64_t exp_time;
-  size_t token_metadata_len;
-
-  //Remote nonce
-  nonce_str = NULL;
-  GNUNET_asprintf (&nonce_str, "%lu", handle->nonce);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
-
-  GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
-                                      &pub_key);
-  handle->ticket = ticket_create (handle->nonce,
-                                  &pub_key,
-                                  handle->label,
-                                  &handle->aud_key);
-
-  time = GNUNET_TIME_absolute_get().abs_value_us;
-  exp_time = time + token_expiration_interval.rel_value_us;
-
-  token_add_attr_int (handle->token, "nbf", time);
-  token_add_attr_int (handle->token, "iat", time);
-  token_add_attr_int (handle->token, "exp", exp_time);
-  token_add_attr (handle->token, "nonce", nonce_str);
-
-  //Token in a serialized encrypted format
-  GNUNET_assert (token_serialize (handle->token,
-                                  &handle->iss_key,
-                                  &ecdhe_privkey,
-                                  &enc_token_str));
-
-  //Token record E,E_K (Token)
-  token_record[0].data = enc_token_str;
-  token_record[0].data_size = strlen (enc_token_str) + 1;
-  token_record[0].expiration_time = exp_time;
-  token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
-  token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
-
-
-  token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
-    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
-    + strlen (handle->scopes) + 1; //With 0-Terminator
-  token_metadata = GNUNET_malloc (token_metadata_len);
-  write_ptr = token_metadata;
-  GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct 
GNUNET_CRYPTO_EcdhePrivateKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
-  GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-  GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); 
//with 0-Terminator;
-
-  token_record[1].data = token_metadata;
-  token_record[1].data_size = token_metadata_len;
-  token_record[1].expiration_time = exp_time;
-  token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
-  token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
-
-  //Persist token
-  handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                                  &handle->iss_key,
-                                                  handle->label,
-                                                  2,
-                                                  token_record,
-                                                  &store_token_issue_cont,
-                                                  handle);
-  GNUNET_free (ecdhe_privkey);
-  GNUNET_free (nonce_str);
-  GNUNET_free (enc_token_str);
-  GNUNET_free (token_metadata);
+  struct AttributeStoreHandle *as_handle = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+  char* buf;
+  char* policy;
+  char* enc_buf;
+  char* rd_buf;
+  size_t enc_size;
+  size_t buf_size;
+  uint32_t attr_ver;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Storing attribute\n");
+  buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
+  buf = GNUNET_malloc (buf_size);
+
+  GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
+                       buf);
+
+  GNUNET_asprintf (&policy,
+                   "%s_%lu",
+                   as_handle->claim->name,
+                   as_handle->claim->version);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Encrypting with policy %s\n", policy);
+  /**
+   * Encrypt the attribute value and store in namestore
+   */
+  enc_size = GNUNET_ABE_cpabe_encrypt (buf,
+                                          buf_size,
+                                          policy, //Policy
+                                          as_handle->abe_key,
+                                          (void**)&enc_buf);
+  GNUNET_free (buf);
+  GNUNET_free (policy);
+  rd[0].data_size = enc_size + sizeof (uint32_t);
+  rd_buf = GNUNET_malloc (rd[0].data_size);
+  attr_ver = htonl (as_handle->claim->version);
+  GNUNET_memcpy (rd_buf,
+                 &attr_ver,
+                 sizeof (uint32_t));
+  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+                 enc_buf,
+                 enc_size);
+  rd[0].data = rd_buf;
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
+  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+  rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+  as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                                     &as_handle->identity,
+                                                     as_handle->claim->name,
+                                                     1,
+                                                     rd,
+                                                     &attr_store_cont,
+                                                     as_handle);
+  GNUNET_free (enc_buf);
+  GNUNET_free (rd_buf);
 }
 
 
 static void
-attr_collect_error (void *cls)
+store_after_abe_bootstrap (void *cls,
+                           struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finished ABE bootstrap\n");
+  struct AttributeStoreHandle *ash = cls;
+  ash->abe_key = abe_key;
+  GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
+}
+
+static int
+check_attribute_store_message(void *cls,
+                              const struct AttributeStoreMessage *sam)
 {
-  struct IssueHandle *handle = cls;
+  uint16_t size;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n");
-  handle->ns_it = NULL;
-  GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+  size = ntohs (sam->header.size);
+  if (size <= sizeof (struct AttributeStoreMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
 }
 
 
 static void
-attr_collect_finished (void *cls)
+handle_attribute_store_message (void *cls,
+                                const struct AttributeStoreMessage *sam)
 {
-  struct IssueHandle *handle = cls;
+  struct AttributeStoreHandle *as_handle;
+  struct IdpClient *idp = cls;
+  size_t data_len;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_STORE message\n");
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
-  handle->ns_it = NULL;
-  GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+  data_len = ntohs (sam->attr_len);
+
+  as_handle = GNUNET_new (struct AttributeStoreHandle);
+  as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
+                                                data_len);
+
+  as_handle->r_id = ntohl (sam->id);
+  as_handle->identity = sam->identity;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
+                                      &as_handle->identity_pkey);
+
+  GNUNET_SERVICE_client_continue (idp->client);
+  as_handle->client = idp;
+  bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, 
GNUNET_NO);
 }
 
+static void
+cleanup_iter_handle (struct AttributeIterator *ai)
+{
+  if (NULL != ai->abe_key)
+    GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
+  GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
+                               ai->client->op_tail,
+                               ai);
+  GNUNET_free (ai);
+}
 
-/**
- * Collect attributes for token
- */
 static void
-attr_collect (void *cls,
+attr_iter_error (void *cls)
+{
+  struct AttributeIterator *ai = cls;
+  //TODO
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed to iterate over attributes\n");
+  cleanup_iter_handle (ai);
+  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+static void
+attr_iter_finished (void *cls)
+{
+  struct AttributeIterator *ai = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeResultMessage *arm;
+
+  env = GNUNET_MQ_msg (arm,
+                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+  arm->id = htonl (ai->request_id);
+  arm->attr_len = htons (0);
+  GNUNET_MQ_send (ai->client->mq, env);
+  cleanup_iter_handle (ai);
+}
+
+static void
+attr_iter_cb (void *cls,
               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
               const char *label,
               unsigned int rd_count,
               const struct GNUNET_GNSRECORD_Data *rd)
 {
-  struct IssueHandle *handle = cls;
-  int i;
-  char* data;
-  struct GNUNET_HashCode key;
-
-  GNUNET_CRYPTO_hash (label,
-                      strlen (label),
-                      &key);
-
-  if (0 == rd_count ||
-      ( (NULL != handle->attr_map) &&
-        (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains 
(handle->attr_map,
-                                                               &key))
-      )
-     )
+  struct AttributeIterator *ai = cls;
+  struct AttributeResultMessage *arm;
+  struct GNUNET_ABE_AbeKey *key;
+  struct GNUNET_MQ_Envelope *env;
+  ssize_t msg_extra_len;
+  char* attr_ser;
+  char* attrs[2];
+  char* data_tmp;
+  char* policy;
+  uint32_t attr_ver;
+
+  if (rd_count != 1)
   {
-    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
     return;
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
-
-  if (1 == rd_count)
-  {
-    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
-                                               rd->data,
-                                               rd->data_size);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
-      token_add_attr (handle->token,
-                      label,
-                      data);
-      GNUNET_free (data);
-    }
-    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+  if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
     return;
   }
+  attr_ver = ntohl(*((uint32_t*)rd->data));
+  GNUNET_asprintf (&policy, "%s_%lu",
+                   label, attr_ver);
+  attrs[0] = policy;
+  attrs[1] = 0;
+  key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
+                                        attrs);
+  msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
+                                               rd->data_size-sizeof (uint32_t),
+                                               key,
+                                               (void**)&attr_ser);
+
+  GNUNET_ABE_cpabe_delete_key (key,
+                                  GNUNET_YES);
+  //GNUNET_free (policy);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Found attribute: %s\n", label);
+  env = GNUNET_MQ_msg_extra (arm,
+                             msg_extra_len,
+                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+  arm->id = htonl (ai->request_id);
+  arm->attr_len = htons (msg_extra_len);
+  GNUNET_CRYPTO_ecdsa_key_get_public (zone,
+                                      &arm->identity);
+  data_tmp = (char *) &arm[1];
+  GNUNET_memcpy (data_tmp,
+                 attr_ser,
+                 msg_extra_len);
+  GNUNET_MQ_send (ai->client->mq, env);
+  GNUNET_free (attr_ser);
+  GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
+  ai->abe_key = NULL;
+}
 
-  i = 0;
-  for (; i < rd_count; i++)
-  {
-    if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
-    {
-      data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
-                                               rd[i].data,
-                                               rd[i].data_size);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
-      token_add_attr (handle->token, label, data);
-      GNUNET_free (data);
-    }
-  }
 
-  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+void
+iterate_after_abe_bootstrap (void *cls,
+                             struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  struct AttributeIterator *ai = cls;
+  ai->abe_key = abe_key;
+  ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                     &ai->identity,
+                                                     &attr_iter_error,
+                                                     ai,
+                                                     &attr_iter_cb,
+                                                     ai,
+                                                     &attr_iter_finished,
+                                                     ai);
+}
+
+void
+iterate_next_after_abe_bootstrap (void *cls,
+                                  struct GNUNET_ABE_AbeMasterKey *abe_key)
+{
+  struct AttributeIterator *ai = cls;
+  ai->abe_key = abe_key;
+  GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
 }
 
+
+
 static void
-cleanup_exchange_handle (struct ExchangeHandle *handle)
+handle_iteration_start (void *cls,
+                        const struct AttributeIterationStartMessage *ais_msg)
 {
-  if (NULL != handle->ticket)
-    ticket_destroy (handle->ticket);
-  if (NULL != handle->token)
-    token_destroy (handle->token);
-  GNUNET_free (handle);
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_ITERATION_START message\n");
+  ai = GNUNET_new (struct AttributeIterator);
+  ai->request_id = ntohl (ais_msg->id);
+  ai->client = idp;
+  ai->identity = ais_msg->identity;
+
+  GNUNET_CONTAINER_DLL_insert (idp->op_head,
+                               idp->op_tail,
+                               ai);
+  bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
 }
 
+
 static void
-process_lookup_result (void *cls, uint32_t rd_count,
-                       const struct GNUNET_GNSRECORD_Data *rd)
+handle_iteration_stop (void *cls,
+                       const struct AttributeIterationStopMessage *ais_msg)
 {
-  struct ExchangeHandle *handle = cls;
-  struct GNUNET_MQ_Envelope *env;
-  char* token_str;
-  char* record_str;
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+  uint32_t rid;
 
-  handle->lookup_request = NULL;
-  if (2 != rd_count)
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "ATTRIBUTE_ITERATION_STOP");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->op_head; NULL != ai; ai = ai->next)
+    if (ai->request_id == rid)
+      break;
+  if (NULL == ai)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Number of tokens %d != 2.",
-                rd_count);
-    cleanup_exchange_handle (handle);
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (idp->client);
     return;
   }
-
-  record_str =
-    GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN,
-                                      rd->data,
-                                      rd->data_size);
-
-  //Decrypt and parse
-  GNUNET_assert (GNUNET_OK ==  token_parse (record_str,
-                                            &handle->aud_privkey,
-                                            &handle->token));
-
-  //Readable
-  GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
-                                               &handle->aud_privkey,
-                                               &token_str));
-
-  env = create_exchange_result_message (token_str,
-                                        handle->label,
-                                        handle->ticket->payload->nonce,
-                                        handle->r_id);
-  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
-                  env);
-  cleanup_exchange_handle (handle);
-  GNUNET_free (record_str);
-  GNUNET_free (token_str);
+  GNUNET_CONTAINER_DLL_remove (idp->op_head,
+                               idp->op_tail,
+                               ai);
+  GNUNET_free (ai);
+  GNUNET_SERVICE_client_continue (idp->client);
 }
 
-/**
- * Checks a exchange message
- *
- * @param cls client sending the message
- * @param xm message of type `struct ExchangeMessage`
- * @return #GNUNET_OK if @a xm is well-formed
- */
-static int
-check_exchange_message (void *cls,
-                        const struct ExchangeMessage *xm)
+
+static void
+handle_iteration_next (void *cls,
+                       const struct AttributeIterationNextMessage *ais_msg)
 {
-  uint16_t size;
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+  uint32_t rid;
 
-  size = ntohs (xm->header.size);
-  if (size <= sizeof (struct ExchangeMessage))
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_ITERATION_NEXT message\n");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->op_head; NULL != ai; ai = ai->next)
+    if (ai->request_id == rid)
+      break;
+  if (NULL == ai)
   {
     GNUNET_break (0);
-    return GNUNET_SYSERR;
+    GNUNET_SERVICE_client_drop (idp->client);
+    return;
   }
-  return GNUNET_OK;
+  bootstrap_abe (&ai->identity,
+                 &iterate_next_after_abe_bootstrap,
+                 ai,
+                 GNUNET_NO);
+  GNUNET_SERVICE_client_continue (idp->client);
 }
 
 /**
- *
- * Handler for exchange message
- *
- * @param cls unused
- * @param client who sent the message
- * @param message the message
+ * Ticket iteration processor result
  */
-static void
-handle_exchange_message (void *cls,
-                         const struct ExchangeMessage *xm)
+enum ZoneIterationResult
 {
-  struct ExchangeHandle *xchange_handle;
-  struct GNUNET_SERVICE_Client *client = cls;
-  const char *ticket;
-  char *lookup_query;
+  /**
+   * Iteration start.
+   */
+  IT_START = 0,
 
-  ticket = (const char *) &xm[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received EXCHANGE of `%s' from client\n",
-              ticket);
-  xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
-  xchange_handle->aud_privkey = xm->aud_privkey;
-  xchange_handle->r_id = xm->id;
-  if (GNUNET_SYSERR == ticket_parse (ticket,
-                                     &xchange_handle->aud_privkey,
-                                     &xchange_handle->ticket))
-  {
-    GNUNET_free (xchange_handle);
-    GNUNET_SERVICE_client_drop (client);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for token under %s\n",
-              xchange_handle->ticket->payload->label);
-  GNUNET_asprintf (&lookup_query,
-                   "%s.gnu",
-                   xchange_handle->ticket->payload->label);
-  GNUNET_SERVICE_client_continue (client);
-  xchange_handle->client = client;
-  xchange_handle->lookup_request
-    = GNUNET_GNS_lookup (gns_handle,
-                         lookup_query,
-                         &xchange_handle->ticket->payload->identity_key,
-                         GNUNET_GNSRECORD_TYPE_ID_TOKEN,
-                         GNUNET_GNS_LO_LOCAL_MASTER,
-                         &process_lookup_result,
-                         xchange_handle);
-  GNUNET_free (lookup_query);
+  /**
+   * Found tickets,
+   * Continue to iterate with next iteration_next call
+   */
+  IT_SUCCESS_MORE_AVAILABLE = 1,
 
-}
+  /**
+   * Iteration complete
+   */
+  IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
+};
 
 
-static void
-find_existing_token_error (void *cls)
+/**
+ * Context for ticket iteration
+ */
+struct TicketIterationProcResult
 {
-  struct IssueHandle *handle = cls;
-  cleanup_issue_handle (handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n");
-  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-}
+  /**
+   * The ticket iteration handle
+   */
+  struct TicketIteration *ti;
+
+  /**
+   * Iteration result: iteration done?
+   * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
+   * we got one for now and have sent it to the client
+   * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
+   * #IT_START: if we are still trying to find a result.
+   */
+  int res_iteration_finished;
 
+};
 
 static void
-find_existing_token_finished (void *cls)
+cleanup_ticket_iter_handle (struct TicketIteration *ti)
 {
-  struct IssueHandle *handle = cls;
-  uint64_t rnd_key;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              ">>> No existing token found\n");
-  rnd_key =
-    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
-                              UINT64_MAX);
-  GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
-                                sizeof (uint64_t),
-                                &handle->label);
-  handle->ns_it = NULL;
-  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                         &handle->iss_key,
-                                                         &attr_collect_error,
-                                                         handle,
-                                                         &attr_collect,
-                                                         handle,
-                                                         
&attr_collect_finished,
-                                                         handle);
+  GNUNET_free (ti);
 }
 
-
 /**
+ * Process ticket from database
  *
- * Look for existing token
- *
- * @param cls the identity entry
- * @param zone the identity
- * @param lbl the name of the record
- * @param rd_count number of records
- * @param rd record data
- *
+ * @param cls struct TicketIterationProcResult
+ * @param ticket the ticket
+ * @param attrs the attributes
  */
 static void
-find_existing_token (void *cls,
-                     const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                     const char *lbl,
-                     unsigned int rd_count,
-                     const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct IssueHandle *handle = cls;
-  const struct GNUNET_GNSRECORD_Data *token_metadata_record;
-  struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
-  struct GNUNET_HashCode key;
-  int scope_count_token;
-  char *scope;
-  char *tmp_scopes;
+ticket_iterate_proc (void *cls,
+                     const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                     const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
+{
+  struct TicketIterationProcResult *proc = cls;
 
-  //There should be only a single record for a token under a label
-  if (2 != rd_count)
+  if (NULL == ticket)
   {
-    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Iteration done\n");
+    proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
     return;
   }
+  proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
+  send_ticket_result (proc->ti->client,
+                      proc->ti->r_id,
+                      ticket,
+                      attrs);
 
-  if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
-  {
-    token_metadata_record = &rd[0];
-  }
-  else
-  {
-    token_metadata_record = &rd[1];
-  }
-  if (token_metadata_record->record_type != 
GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-    return;
-  }
-  ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey 
*)token_metadata_record->data);
-  aud_key =
-    (struct GNUNET_CRYPTO_EcdsaPublicKey 
*)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
-  tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+}
 
-  if (0 != memcmp (aud_key, &handle->aud_key,
-                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-  {
-    char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key,
-                                                      sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-    //Audience does not match!
-    char *tmp = GNUNET_GNSRECORD_value_to_string 
(GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA,
-                                                  token_metadata_record->data,
-                                                  
token_metadata_record->data_size);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Token does not match audience %s vs %s. Moving on\n",
-                tmp2,
-                tmp);
-    GNUNET_free (tmp_scopes);
-    GNUNET_free (tmp2);
-    GNUNET_free (tmp);
-    GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-    return;
-  }
+/**
+ * Perform ticket iteration step
+ *
+ * @param ti ticket iterator to process
+ */
+static void
+run_ticket_iteration_round (struct TicketIteration *ti)
+{
+  struct TicketIterationProcResult proc;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketResultMessage *trm;
+  int ret;
 
-  scope = strtok (tmp_scopes, ",");
-  scope_count_token = 0;
-  while (NULL != scope)
+  memset (&proc, 0, sizeof (proc));
+  proc.ti = ti;
+  proc.res_iteration_finished = IT_START;
+  while (IT_START == proc.res_iteration_finished)
   {
-    GNUNET_CRYPTO_hash (scope,
-                        strlen (scope),
-                        &key);
-
-    if ((NULL != handle->attr_map) &&
-        (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains 
(handle->attr_map, &key)))
+    if (GNUNET_SYSERR ==
+        (ret = TKT_database->iterate_tickets (TKT_database->cls,
+                                              &ti->identity,
+                                              ti->is_audience,
+                                              ti->offset,
+                                              &ticket_iterate_proc,
+                                              &proc)))
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Issued token does not include `%s'. Moving on\n", scope);
-      GNUNET_free (tmp_scopes);
-      GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
-      return;
+      GNUNET_break (0);
+      break;
     }
-    scope_count_token++;
-    scope = strtok (NULL, ",");
+    if (GNUNET_NO == ret)
+      proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
+    ti->offset++;
   }
-  GNUNET_free (tmp_scopes);
-  //All scopes in token are also in request. Now
-  //Check length
-  if ((NULL != handle->attr_map) &&
-      (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == 
scope_count_token))
+  if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
   {
-    //We have an existing token
-    handle->label = GNUNET_strdup (lbl);
-    handle->ns_it = NULL;
-    handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                           &handle->iss_key,
-                                                           &attr_collect_error,
-                                                           handle,
-                                                           &attr_collect,
-                                                           handle,
-                                                           
&attr_collect_finished,
-                                                           handle);
-
-    return;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "More results available\n");
+    return; /* more later */
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Nuber of attributes in token do not match request\n");
-  //No luck
-  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+  /* send empty response to indicate end of list */
+  env = GNUNET_MQ_msg (trm,
+                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
+  trm->id = htonl (ti->r_id);
+  GNUNET_MQ_send (ti->client->mq,
+                  env);
+  GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
+                               ti->client->ticket_iter_tail,
+                               ti);
+  cleanup_ticket_iter_handle (ti);
 }
 
-/**
- * Checks an issue message
- *
- * @param cls client sending the message
- * @param im message of type `struct IssueMessage`
- * @return #GNUNET_OK if @a im is well-formed
- */
-static int
-check_issue_message(void *cls,
-                    const struct IssueMessage *im)
+static void
+handle_ticket_iteration_start (void *cls,
+                               const struct TicketIterationStartMessage 
*tis_msg)
 {
-  uint16_t size;
+  struct IdpClient *client = cls;
+  struct TicketIteration *ti;
 
-  size = ntohs (im->header.size);
-  if (size <= sizeof (struct IssueMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  scopes = (char *) &im[1];
-  if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received TICKET_ITERATION_START message\n");
+  ti = GNUNET_new (struct TicketIteration);
+  ti->r_id = ntohl (tis_msg->id);
+  ti->offset = 0;
+  ti->client = client;
+  ti->identity = tis_msg->identity;
+  ti->is_audience = ntohl (tis_msg->is_audience);
+
+  GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
+                               client->ticket_iter_tail,
+                               ti);
+  run_ticket_iteration_round (ti);
+  GNUNET_SERVICE_client_continue (client->client);
+}
+
+
+static void
+handle_ticket_iteration_stop (void *cls,
+                              const struct TicketIterationStopMessage *tis_msg)
+{
+  struct IdpClient *client = cls;
+  struct TicketIteration *ti;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "TICKET_ITERATION_STOP");
+  rid = ntohl (tis_msg->id);
+  for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
+    if (ti->r_id == rid)
+      break;
+  if (NULL == ti)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Malformed scopes received!\n");
     GNUNET_break (0);
-    return GNUNET_SYSERR;
+    GNUNET_SERVICE_client_drop (client->client);
+    return;
   }
-  return GNUNET_OK;
+  GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
+                               client->ticket_iter_tail,
+                               ti);
+  cleanup_ticket_iter_handle (ti);
+  GNUNET_SERVICE_client_continue (client->client);
 }
 
-/**
- *
- * Handler for issue message
- *
- * @param cls unused
- * @param client who sent the message
- * @param message the message
- */
+
 static void
-handle_issue_message (void *cls,
-                      const struct IssueMessage *im)
+handle_ticket_iteration_next (void *cls,
+                              const struct TicketIterationNextMessage *tis_msg)
 {
-  const char *scopes;
-  char *scopes_tmp;
-  char *scope;
-  struct GNUNET_HashCode key;
-  struct IssueHandle *issue_handle;
-  struct GNUNET_SERVICE_Client *client = cls;
-
-  scopes = (const char *) &im[1];
-  issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
-  issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
-                                                                 GNUNET_NO);
-  scopes_tmp = GNUNET_strdup (scopes);
+  struct IdpClient *client = cls;
+  struct TicketIteration *ti;
+  uint32_t rid;
 
-  for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, 
","))
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received TICKET_ITERATION_NEXT message\n");
+  rid = ntohl (tis_msg->id);
+  for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
+    if (ti->r_id == rid)
+      break;
+  if (NULL == ti)
   {
-    GNUNET_CRYPTO_hash (scope,
-                        strlen (scope),
-                        &key);
-    GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
-                                       &key,
-                                       scope,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (client->client);
+    return;
   }
-  GNUNET_free (scopes_tmp);
-  issue_handle->r_id = im->id;
-  issue_handle->aud_key = im->aud_key;
-  issue_handle->iss_key = im->iss_key;
-  GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
-                                      &issue_handle->iss_pkey);
-  issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
-  issue_handle->nonce = ntohl (im->nonce);
-  GNUNET_SERVICE_client_continue (client);
-  issue_handle->client = client;
-  issue_handle->scopes = GNUNET_strdup (scopes);
-  issue_handle->token = token_create (&issue_handle->iss_pkey,
-                                      &issue_handle->aud_key);
-
-  issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                               &im->iss_key,
-                                                               
&find_existing_token_error,
-                                                               issue_handle,
-                                                               
&find_existing_token,
-                                                               issue_handle,
-                                                               
&find_existing_token_finished,
-                                                               issue_handle);
+  run_ticket_iteration_round (ti);
+  GNUNET_SERVICE_client_continue (client->client);
 }
 
 
+
+
 /**
  * Main function that will be run
  *
  * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL)
- * @param c configuration
+ * @param c the configuration used 
+ * @param server the service handle
  */
 static void
 run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *c,
      struct GNUNET_SERVICE_Handle *server)
 {
+  char *database;
   cfg = c;
 
   stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
@@ -1606,10 +2384,38 @@ run (void *cls,
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
   }
-
+  credential_handle = GNUNET_CREDENTIAL_connect (cfg);
+  if (NULL == credential_handle)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to 
credential");
+  }
   identity_handle = GNUNET_IDENTITY_connect (cfg,
-                                             &list_ego,
+                                             NULL,
                                              NULL);
+  stats_handle = GNUNET_STATISTICS_create ("identity-provider",
+                                           cfg);
+  /* Loading DB plugin */
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "identity-provider",
+                                             "database",
+                                             &database))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No database backend configured\n");
+  GNUNET_asprintf (&db_lib_name,
+                   "libgnunet_plugin_identity_provider_%s",
+                   database);
+  TKT_database = GNUNET_PLUGIN_load (db_lib_name,
+                                     (void *) cfg);
+  GNUNET_free (database);
+  if (NULL == TKT_database)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not load database backend `%s'\n",
+                db_lib_name);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
 
   if (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -1640,9 +2446,39 @@ client_disconnect_cb (void *cls,
                       struct GNUNET_SERVICE_Client *client,
                       void *app_ctx)
 {
+  struct IdpClient *idp = app_ctx;
+  struct AttributeIterator *ai;
+  struct TicketIteration *ti;
+  struct TicketRevocationHandle *rh;
+
+  //TODO other operations
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Client %p disconnected\n",
               client);
+
+  while (NULL != (ai = idp->op_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->op_head,
+                                 idp->op_tail,
+                                 ai);
+    GNUNET_free (ai);
+  }
+  while (NULL != (rh = idp->revocation_list_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
+                                 idp->revocation_list_tail,
+                                 rh);
+    cleanup_revoke_ticket_handle (rh);
+  }
+  while (NULL != (ti = idp->ticket_iter_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
+                                 idp->ticket_iter_tail,
+                                 ti);
+    cleanup_ticket_iter_handle (ti);
+  }
+  GNUNET_free (idp);
 }
 
 
@@ -1659,10 +2495,14 @@ client_connect_cb (void *cls,
                    struct GNUNET_SERVICE_Client *client,
                    struct GNUNET_MQ_Handle *mq)
 {
+  struct IdpClient *idp;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Client %p connected\n",
               client);
-  return client;
+  idp = GNUNET_new (struct IdpClient);
+  idp->client = client;
+  idp->mq = mq;
+  return idp;
 }
 
 
@@ -1677,13 +2517,45 @@ GNUNET_SERVICE_MAIN
  &client_connect_cb,
  &client_disconnect_cb,
  NULL,
- GNUNET_MQ_hd_var_size (issue_message,
-                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE,
-                        struct IssueMessage,
+ GNUNET_MQ_hd_var_size (attribute_store_message,
+                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
+                        struct AttributeStoreMessage,
+                        NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_start, 
+                          
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
+                          struct AttributeIterationStartMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_next, 
+                          
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
+                          struct AttributeIterationNextMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_stop, 
+                          
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
+                          struct AttributeIterationStopMessage,
+                          NULL),
+ GNUNET_MQ_hd_var_size (issue_ticket_message,
+                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
+                        struct IssueTicketMessage,
+                        NULL),
+ GNUNET_MQ_hd_var_size (consume_ticket_message,
+                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
+                        struct ConsumeTicketMessage,
                         NULL),
- GNUNET_MQ_hd_var_size (exchange_message,
-                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
-                        struct ExchangeMessage,
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_start, 
+                          
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
+                          struct TicketIterationStartMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_next, 
+                          
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
+                          struct TicketIterationNextMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, 
+                          
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
+                          struct TicketIterationStopMessage,
+                          NULL),
+ GNUNET_MQ_hd_var_size (revoke_ticket_message,
+                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
+                        struct RevokeTicketMessage,
                         NULL),
  GNUNET_MQ_handler_end());
 /* end of gnunet-service-identity-provider.c */
diff --git a/src/identity-provider/identity-provider.conf 
b/src/identity-provider/identity-provider.conf
index bac8e69ed..7ee5e50d8 100644
--- a/src/identity-provider/identity-provider.conf
+++ b/src/identity-provider/identity-provider.conf
@@ -10,3 +10,7 @@ UNIXPATH = 
$GNUNET_USER_RUNTIME_DIR/gnunet-service-identity-provider.sock
 UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 TOKEN_EXPIRATION_INTERVAL = 30 m
+DATABASE = sqlite
+
+[identity-provider-sqlite]
+FILENAME = $GNUNET_DATA_HOME/identity-provider/sqlite.db
diff --git a/src/identity-provider/identity_provider.h 
b/src/identity-provider/identity_provider.h
index 6fe6102c8..b1fe6e1fd 100644
--- a/src/identity-provider/identity_provider.h
+++ b/src/identity-provider/identity_provider.h
@@ -34,34 +34,157 @@
 GNUNET_NETWORK_STRUCT_BEGIN
 
 /**
- * The token
+ * Use to store an identity attribute
  */
-struct GNUNET_IDENTITY_PROVIDER_Token
+struct AttributeStoreMessage
 {
   /**
-   * The JWT representation of the identity token
+   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
    */
-  char *data;
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * The length of the attribute
+   */
+  uint32_t attr_len GNUNET_PACKED;
+
+  /**
+   * Identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /* followed by the serialized attribute */
+
 };
 
 /**
- * The ticket
+ * Attribute store response message
  */
-struct GNUNET_IDENTITY_PROVIDER_Ticket
+struct AttributeStoreResultMessage
 {
   /**
-   * The Base64 representation of the ticket
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * #GNUNET_SYSERR on failure, #GNUNET_OK on success
+   */
+  int32_t op_result GNUNET_PACKED;
+
+};
+
+/**
+ * Attribute is returned from the idp.
+ */
+struct AttributeResultMessage
+{
+  /**
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+
+   /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Length of serialized attribute data
+   */
+  uint16_t attr_len GNUNET_PACKED;
+
+  /**
+   * always zero (for alignment)
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+  /**
+   * The public key of the identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /* followed by:
+   * serialized attribute data
+   */
+};
+
+
+/**
+ * Start a attribute iteration for the given identity
+ */
+struct AttributeIterationStartMessage
+{
+  /**
+   * Message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+};
+
+
+/**
+ * Ask for next result of attribute iteration for the given operation
+ */
+struct AttributeIterationNextMessage
+{
+  /**
+   * Type will be 
#GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+
+/**
+ * Stop attribute iteration for the given operation
+ */
+struct AttributeIterationStopMessage
+{
+  /**
+   * Type will be 
#GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
    */
-  char *data;
+  uint32_t id GNUNET_PACKED;
+
 };
 
 /**
- * Answer from service to client after issue operation
+ * Start a ticket iteration for the given identity
  */
-struct IssueResultMessage
+struct TicketIterationStartMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE
+   * Message
    */
   struct GNUNET_MessageHeader header;
 
@@ -70,18 +193,25 @@ struct IssueResultMessage
    */
   uint32_t id GNUNET_PACKED;
 
-  /* followed by 0-terminated label,ticket,token */
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
 
+  /**
+   * Identity is audience or issuer
+   */
+  uint32_t is_audience GNUNET_PACKED;
 };
 
 
 /**
- * Ticket exchange message.
+ * Ask for next result of ticket iteration for the given operation
  */
-struct ExchangeResultMessage
+struct TicketIterationNextMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT
    */
   struct GNUNET_MessageHeader header;
 
@@ -90,25 +220,35 @@ struct ExchangeResultMessage
    */
   uint32_t id GNUNET_PACKED;
 
+};
+
+
+/**
+ * Stop ticket iteration for the given operation
+ */
+struct TicketIterationStopMessage
+{
   /**
-   * Nonce found in ticket. NBO
-   * 0 on error.
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP
    */
-  uint64_t ticket_nonce GNUNET_PACKED;
+  struct GNUNET_MessageHeader header;
 
-  /* followed by 0-terminated token */
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
 
 };
 
 
 
 /**
- * Client requests IdP to issue token.
+ * Ticket issue message
  */
-struct IssueMessage
+struct IssueTicketMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET
    */
   struct GNUNET_MessageHeader header;
 
@@ -117,40 +257,98 @@ struct IssueMessage
    */
   uint32_t id GNUNET_PACKED;
 
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
   /**
-   * Issuer identity private key
+   * Requesting party.
    */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey rp;
 
   /**
-   * Audience public key
+   * length of serialized attribute list
    */
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
+  uint32_t attr_len GNUNET_PACKED;
 
+  //Followed by a serialized attribute list
+};
+
+/**
+ * Ticket revoke message
+ */
+struct RevokeTicketMessage
+{
   /**
-   * Nonce
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET
    */
-  uint64_t nonce;
+  struct GNUNET_MessageHeader header;
 
   /**
-   * Expiration of token in NBO.
+   * Unique identifier for this request (for key collisions).
    */
-  struct GNUNET_TIME_AbsoluteNBO expiration;
+  uint32_t id GNUNET_PACKED;
 
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
-  /* followed by 0-terminated comma-separated scope list */
+  /**
+   * length of serialized attribute list
+   */
+  uint32_t attrs_len GNUNET_PACKED;
 
+  //Followed by a ticket and serialized attribute list
+};
+
+/**
+ * Ticket revoke message
+ */
+struct RevokeTicketResultMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Revocation result
+   */
+  uint32_t success GNUNET_PACKED;
 };
 
 
 /**
- * Use to exchange a ticket for a token
+ * Ticket result message
  */
-struct ExchangeMessage
+struct TicketResultMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+/**
+ * Ticket consume message
+ */
+struct ConsumeTicketMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET
    */
   struct GNUNET_MessageHeader header;
 
@@ -160,15 +358,50 @@ struct ExchangeMessage
   uint32_t id GNUNET_PACKED;
 
   /**
-   * Audience identity private key
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  //Followed by a serialized ticket
+};
+
+/**
+ * Attribute list is returned from the idp.
+ */
+struct ConsumeTicketResultMessage
+{
+  /**
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+
+   /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Length of serialized attribute data
    */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
+  uint16_t attrs_len GNUNET_PACKED;
 
-  /* followed by 0-terminated ticket string */
+  /**
+   * always zero (for alignment)
+   */
+  uint16_t reserved GNUNET_PACKED;
 
+  /**
+   * The public key of the identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /* followed by:
+   * serialized attributes data
+   */
 };
 
 
+
 GNUNET_NETWORK_STRUCT_END
 
 #endif
diff --git a/src/identity-provider/identity_provider_api.c 
b/src/identity-provider/identity_provider_api.c
index 845d1f753..d0ece80fe 100644
--- a/src/identity-provider/identity_provider_api.c
+++ b/src/identity-provider/identity_provider_api.c
@@ -29,12 +29,12 @@
 #include "gnunet_protocols.h"
 #include "gnunet_mq_lib.h"
 #include "gnunet_identity_provider_service.h"
+#include "gnunet_identity_attribute_lib.h"
 #include "identity_provider.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
 
 
-
 /**
  * Handle for an operation with the service.
  */
@@ -63,16 +63,24 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
   const struct GNUNET_MessageHeader *msg;
 
   /**
-   * Continuation to invoke with the result of the transmission; @e cb
-   * will be NULL in this case.
+   * Continuation to invoke after attribute store call
+   */
+  GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb;
+
+  /**
+   * Attribute result callback
+   */
+  GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb;
+  
+  /**
+   * Revocation result callback
    */
-  GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb;
+  GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb;
 
   /**
-   * Continuation to invoke with the result of the transmission for
-   * 'issue' operations (@e cont will be NULL in this case).
+   * Ticket result callback
    */
-  GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb;
+  GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
 
   /**
    * Envelope with the message for this queue entry.
@@ -91,6 +99,140 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
 
 };
 
+/**
+ * Handle for a ticket iterator operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *prev;
+
+  /**
+   * Main handle to access the idp.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
+
+  /**
+   * Function to call on completion.
+   */
+  GNUNET_SCHEDULER_TaskCallback finish_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *finish_cb_cls;
+
+  /**
+   * The continuation to call with the results
+   */
+  GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
+
+  /**
+   * Closure for @e tr_cb.
+   */
+  void *cls;
+
+  /**
+   * Function to call on errors.
+   */
+  GNUNET_SCHEDULER_TaskCallback error_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *error_cb_cls;
+
+  /**
+   * Envelope of the message to send to the service, if not yet
+   * sent.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * The operation id this zone iteration operation has
+   */
+  uint32_t r_id;
+
+};
+
+
+/**
+ * Handle for a attribute iterator operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_AttributeIterator
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev;
+
+  /**
+   * Main handle to access the idp.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
+
+  /**
+   * Function to call on completion.
+   */
+  GNUNET_SCHEDULER_TaskCallback finish_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *finish_cb_cls;
+
+  /**
+   * The continuation to call with the results
+   */
+  GNUNET_IDENTITY_PROVIDER_AttributeResult proc;
+
+  /**
+   * Closure for @e proc.
+   */
+  void *proc_cls;
+
+  /**
+   * Function to call on errors.
+   */
+  GNUNET_SCHEDULER_TaskCallback error_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *error_cb_cls;
+
+  /**
+   * Envelope of the message to send to the service, if not yet
+   * sent.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * Private key of the zone.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * The operation id this zone iteration operation has
+   */
+  uint32_t r_id;
+
+};
+
 
 /**
  * Handle for the service.
@@ -123,6 +265,27 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
   struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail;
 
   /**
+   * Head of active iterations
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head;
+
+  /**
+   * Tail of active iterations
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail;
+
+  /**
+   * Head of active iterations
+   */
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head;
+
+  /**
+   * Tail of active iterations
+   */
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail;
+
+
+  /**
    * Currently pending transmission request, or NULL for none.
    */
   struct GNUNET_CLIENT_TransmitHandle *th;
@@ -154,14 +317,13 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
 
 };
 
-
 /**
  * Try again to connect to the service.
  *
- * @param cls handle to the service.
+ * @param h handle to the identity provider service.
  */
 static void
-reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle);
+reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h);
 
 /**
  * Reconnect
@@ -181,7 +343,7 @@ reconnect_task (void *cls)
 /**
  * Disconnect from service and then reconnect.
  *
- * @param handle our handle
+ * @param handle our service
  */
 static void
 force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
@@ -197,6 +359,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle 
*handle)
 }
 
 /**
+ * Free @a it.
+ *
+ * @param it entry to free
+ */
+static void
+free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+
+  GNUNET_CONTAINER_DLL_remove (h->it_head,
+                               h->it_tail,
+                               it);
+  if (NULL != it->env)
+    GNUNET_MQ_discard (it->env);
+  GNUNET_free (it);
+}
+
+
+
+/**
  * Generic error handler, called with the appropriate error code and
  * the same closure specified at the creation of the message queue.
  * Not every message queue implementation supports an error handler.
@@ -213,22 +395,68 @@ mq_error_handler (void *cls,
 }
 
 /**
- * Check validity of message received from the service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_attribute_store_response (void *cls,
+                             const struct AttributeStoreResultMessage *msg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  uint32_t r_id = ntohl (msg->id);
+  int res;
+  const char *emsg;
+
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+
+  res = ntohl (msg->op_result);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
+       res);
+
+  /* TODO: add actual error message to response... */
+  if (GNUNET_SYSERR == res)
+    emsg = _("failed to store record\n");
+  else
+    emsg = NULL;
+  if (NULL != op->as_cb)
+    op->as_cb (op->cls,
+              res,
+              emsg);
+  GNUNET_CONTAINER_DLL_remove (h->op_head,
+                               h->op_tail,
+                               op);
+  GNUNET_free (op);
+
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
  *
- * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *`
- * @param result_msg the incoming message
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
-check_exchange_result (void *cls,
-              const struct ExchangeResultMessage *erm)
+check_consume_ticket_result (void *cls,
+                             const struct ConsumeTicketResultMessage *msg)
 {
-  char *str;
-  size_t size = ntohs (erm->header.size) - sizeof (*erm);
-  
+  size_t msg_len;
+  size_t attrs_len;
 
-  str = (char *) &erm[1];
-  if ( (size > sizeof (struct ExchangeResultMessage)) &&
-       ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) )
+  msg_len = ntohs (msg->header.size);
+  attrs_len = ntohs (msg->attrs_len);
+  if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -238,20 +466,85 @@ check_exchange_result (void *cls,
 
 
 /**
- * Check validity of message received from the service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_consume_ticket_result (void *cls,
+                              const struct ConsumeTicketResultMessage *msg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  size_t attrs_len;
+  uint32_t r_id = ntohl (msg->id);
+
+  attrs_len = ntohs (msg->attrs_len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing attribute result.\n");
+
+
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+
+  {
+    struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
+    struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+    attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1],
+                                        attrs_len);
+    if (NULL != op->ar_cb)
+    {
+      if (NULL == attrs)
+      {
+        op->ar_cb (op->cls,
+                   &msg->identity,
+                   NULL);
+      }
+      else
+      {
+        for (le = attrs->list_head; NULL != le; le = le->next)
+          op->ar_cb (op->cls,
+                     &msg->identity,
+                     le->claim);
+        GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
+      }
+    }
+    op->ar_cb (op->cls,
+               NULL,
+               NULL);
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                 h->op_tail,
+                                 op);
+    GNUNET_free (op);
+    return;
+  }
+  GNUNET_assert (0);
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
  *
- * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *`
- * @param result_msg the incoming message
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
-check_result (void *cls,
-              const struct IssueResultMessage *irm)
+check_attribute_result (void *cls,
+                        const struct AttributeResultMessage *msg)
 {
-  char *str;
-  size_t size = ntohs (irm->header.size) - sizeof (*irm);
-  str = (char*) &irm[1];
-  if ( (size > sizeof (struct IssueResultMessage)) &&
-       ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) )
+  size_t msg_len;
+  size_t attr_len;
+
+  msg_len = ntohs (msg->header.size);
+  attr_len = ntohs (msg->attr_len);
+  if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -259,119 +552,254 @@ check_result (void *cls,
   return GNUNET_OK;
 }
 
+
 /**
- * Handler for messages received from the GNS service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
  *
- * @param cls the `struct GNUNET_GNS_Handle *`
- * @param loookup_msg the incoming message
+ * @param cls
+ * @param msg the message we received
  */
 static void
-handle_exchange_result (void *cls,
-                        const struct ExchangeResultMessage *erm)
+handle_attribute_result (void *cls,
+                         const struct AttributeResultMessage *msg)
 {
-  struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
+  static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
   struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct GNUNET_IDENTITY_PROVIDER_Token token;
-  uint64_t ticket_nonce;
-  uint32_t r_id = ntohl (erm->id);
-  char *str;
-  
-  for (op = handle->op_head; NULL != op; op = op->next)
+  size_t attr_len;
+  uint32_t r_id = ntohl (msg->id);
+
+  attr_len = ntohs (msg->attr_len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing attribute result.\n");
+
+
+  for (it = h->it_head; NULL != it; it = it->next)
+    if (it->r_id == r_id)
+      break;
+  for (op = h->op_head; NULL != op; op = op->next)
     if (op->r_id == r_id)
       break;
-  if (NULL == op)
+  if ((NULL == it) && (NULL == op))
     return;
-  str = GNUNET_strdup ((char*)&erm[1]);
-  op = handle->op_head;
-  GNUNET_CONTAINER_DLL_remove (handle->op_head,
-                               handle->op_tail,
-                               op);
-  token.data = str;
-  ticket_nonce = ntohl (erm->ticket_nonce);
-  if (NULL != op->ex_cb)
-    op->ex_cb (op->cls, &token, ticket_nonce);
-  GNUNET_free (str);
-  GNUNET_free (op);
 
+  if ( (0 == (memcmp (&msg->identity,
+                      &identity_dummy,
+                      sizeof (identity_dummy)))) )
+  {
+    if ((NULL == it) && (NULL == op))
+    {
+      GNUNET_break (0);
+      force_reconnect (h);
+      return;
+    }
+    if (NULL != it)
+    {
+      if (NULL != it->finish_cb)
+        it->finish_cb (it->finish_cb_cls);
+      free_it (it);
+    }
+    if (NULL != op) 
+    {
+      if (NULL != op->ar_cb)
+        op->ar_cb (op->cls,
+                   NULL,
+                   NULL);
+      GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                   h->op_tail,
+                                   op);
+      GNUNET_free (op);
+
+    }
+    return;
+  }
+
+  {
+    struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr;
+    attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1],
+                                                  attr_len);
+    if (NULL != it)
+    {
+      if (NULL != it->proc)
+        it->proc (it->proc_cls,
+                  &msg->identity,
+                  attr);
+    } else if (NULL != op)
+    {
+      if (NULL != op->ar_cb)
+        op->ar_cb (op->cls,
+                   &msg->identity,
+                   attr);
+
+    }
+    GNUNET_free (attr);
+    return;
+  }
+  GNUNET_assert (0);
+}
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_ticket_result (void *cls,
+                     const struct TicketResultMessage *msg)
+{
+  size_t msg_len;
+
+  msg_len = ntohs (msg->header.size);
+  if (msg_len < sizeof (struct TicketResultMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
 }
 
+
+
 /**
- * Handler for messages received from the GNS service
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
  *
- * @param cls the `struct GNUNET_GNS_Handle *`
- * @param loookup_msg the incoming message
+ * @param cls
+ * @param msg the message we received
  */
 static void
-handle_result (void *cls,
-               const struct IssueResultMessage *irm)
+handle_ticket_result (void *cls,
+                      const struct TicketResultMessage *msg)
 {
   struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
   struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct GNUNET_IDENTITY_PROVIDER_Token token;
-  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
-  uint32_t r_id = ntohl (irm->id);
-  char *str;
-  char *label_str;
-  char *ticket_str;
-  char *token_str;
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
+  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
+  uint32_t r_id = ntohl (msg->id);
+  size_t msg_len;
 
   for (op = handle->op_head; NULL != op; op = op->next)
     if (op->r_id == r_id)
       break;
-  if (NULL == op)
+  for (it = handle->ticket_it_head; NULL != it; it = it->next)
+    if (it->r_id == r_id)
+      break;
+  if ((NULL == op) && (NULL == it))
     return;
-  str = GNUNET_strdup ((char*)&irm[1]);
-  label_str = strtok (str, ",");
-
-  if (NULL == label_str)
+  msg_len = ntohs (msg->header.size);
+  if (NULL != op)
   {
-    GNUNET_free (str);
-    GNUNET_break (0);
+    GNUNET_CONTAINER_DLL_remove (handle->op_head,
+                                 handle->op_tail,
+                                 op);
+    if (msg_len == sizeof (struct TicketResultMessage))
+    {
+      if (NULL != op->tr_cb)
+        op->tr_cb (op->cls, NULL);
+    } else {
+      ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
+      if (NULL != op->tr_cb)
+        op->tr_cb (op->cls, ticket);
+    }
+    GNUNET_free (op);
     return;
-  }
-  ticket_str = strtok (NULL, ",");
-  if (NULL == ticket_str)
-  {
-    GNUNET_free (str);
-    GNUNET_break (0);
+  } else if (NULL != it) {
+    if (msg_len == sizeof (struct TicketResultMessage))
+    {
+      if (NULL != it->tr_cb)
+        GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
+                                     handle->ticket_it_tail,
+                                     it);
+      it->finish_cb (it->finish_cb_cls);
+      GNUNET_free (it);
+    } else {
+      ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1];
+      if (NULL != it->tr_cb)
+        it->tr_cb (it->cls, ticket);
+    }
     return;
   }
-  token_str = strtok (NULL, ",");
-  if (NULL == token_str)
+  GNUNET_break (0);
+}
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_revoke_ticket_result (void *cls,
+                             const struct RevokeTicketResultMessage *msg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  uint32_t r_id = ntohl (msg->id);
+  int32_t success;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing revocation result.\n");
+
+
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+  success = ntohl (msg->success);
   {
-    GNUNET_free (str);
-    GNUNET_break (0);
+    if (NULL != op->rvk_cb)
+    {
+      op->rvk_cb (op->cls,
+                  success,
+                  NULL);
+    }
+    GNUNET_CONTAINER_DLL_remove (h->op_head,
+                                 h->op_tail,
+                                 op);
+    GNUNET_free (op);
     return;
   }
-  GNUNET_CONTAINER_DLL_remove (handle->op_head,
-                               handle->op_tail,
-                               op);
-  ticket.data = ticket_str;
-  token.data = token_str;
-  if (NULL != op->iss_cb)
-    op->iss_cb (op->cls, label_str, &ticket, &token);
-  GNUNET_free (str);
-  GNUNET_free (op);
-
+  GNUNET_assert (0);
 }
 
+
+
 /**
  * Try again to connect to the service.
  *
- * @param cls handle to the identity provider service.
+ * @param h handle to the identity provider service.
  */
 static void
 reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
 {
   struct GNUNET_MQ_MessageHandler handlers[] = {
-    GNUNET_MQ_hd_var_size (result,
-                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT,
-                           struct IssueResultMessage,
+    GNUNET_MQ_hd_fixed_size (attribute_store_response,
+                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE,
+                             struct AttributeStoreResultMessage,
+                             h),
+    GNUNET_MQ_hd_var_size (attribute_result,
+                           
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
+                           struct AttributeResultMessage,
                            h),
-    GNUNET_MQ_hd_var_size (exchange_result,
-                           
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT,
-                           struct ExchangeResultMessage,
+    GNUNET_MQ_hd_var_size (ticket_result,
+                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT,
+                           struct TicketResultMessage,
                            h),
+    GNUNET_MQ_hd_var_size (consume_ticket_result,
+                           
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT,
+                           struct ConsumeTicketResultMessage,
+                           h),
+    GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
+                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT,
+                             struct RevokeTicketResultMessage,
+                             h),
     GNUNET_MQ_handler_end ()
   };
   struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -417,111 +845,6 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
 
 
 /**
- * Issue an identity token
- *
- * @param id identity service to query
- * @param service_name for which service is an identity wanted
- * @param cb function to call with the result (will only be called once)
- * @param cb_cls closure for @a cb
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle 
*id,
-                                      const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
-                                      const struct 
GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                                      const char* scopes,
-                                      struct GNUNET_TIME_Absolute expiration,
-                                      uint64_t nonce,
-                                      GNUNET_IDENTITY_PROVIDER_IssueCallback 
cb,
-                                      void *cb_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct IssueMessage *im;
-  size_t slen;
-
-  slen = strlen (scopes) + 1;
-  if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct IssueMessage))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
-  op->h = id;
-  op->iss_cb = cb;
-  op->cls = cb_cls;
-  op->r_id = id->r_id_gen++;
-  op->env = GNUNET_MQ_msg_extra (im,
-                                 slen,
-                                 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE);
-  im->id = op->r_id;
-  im->iss_key = *iss_key;
-  im->aud_key = *aud_key;
-  im->nonce = htonl (nonce);
-  im->expiration = GNUNET_TIME_absolute_hton (expiration);
-  GNUNET_memcpy (&im[1], scopes, slen);
-  GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
-                                    id->op_tail,
-                                    op);
-  if (NULL != id->mq)
-    GNUNET_MQ_send_copy (id->mq,
-                         op->env);
-  return op;
-}
-
-
-/**
- * Exchange a token ticket for a token
- *
- * @param id identity provider service
- * @param ticket ticket to exchange
- * @param cont function to call once the operation finished
- * @param cont_cls closure for @a cont
- * @return handle to abort the operation
- */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
-                                          const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                                          const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
-                                          
GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
-                                          void *cont_cls)
-{
-  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
-  struct ExchangeMessage *em;
-  size_t slen;
-  char *ticket_str;
-
-  ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
-
-  slen = strlen (ticket_str) + 1;
-  if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct ExchangeMessage))
-  {
-    GNUNET_free (ticket_str);
-    GNUNET_break (0);
-    return NULL;
-  }
-  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
-  op->h = id;
-  op->ex_cb = cont;
-  op->cls = cont_cls;
-  op->r_id = id->r_id_gen++;
-  op->env = GNUNET_MQ_msg_extra (em,
-                                 slen,
-                                 
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE);
-  em->aud_privkey = *aud_privkey;
-  em->id = htonl (op->r_id);
-  GNUNET_memcpy (&em[1], ticket_str, slen);
-  GNUNET_free (ticket_str);
-  GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
-                                    id->op_tail,
-                                    op);
-  if (NULL != id->mq)
-    GNUNET_MQ_send_copy (id->mq,
-                         op->env);
-  return op;
-}
-
-
-/**
  * Cancel an operation. Note that the operation MAY still
  * be executed; this merely cancels the continuation; if the request
  * was already transmitted, the service may still choose to complete
@@ -566,80 +889,482 @@ GNUNET_IDENTITY_PROVIDER_disconnect (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h)
 }
 
 /**
- * Convenience API
+ * Store an attribute.  If the attribute is already present,
+ * it is replaced with the new attribute.
+ *
+ * @param h handle to the identity provider
+ * @param pkey private key of the identity
+ * @param attr the attribute value
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
  */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_attribute_store (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                          const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+                                          const struct 
GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
+                                          
GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
+                                          void *cont_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct AttributeStoreMessage *sam;
+  size_t attr_len;
+
+  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+  op->h = h;
+  op->as_cb = cont;
+  op->cls = cont_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr);
+  op->env = GNUNET_MQ_msg_extra (sam,
+                                 attr_len,
+                                 
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE);
+  sam->identity = *pkey;
+  sam->id = htonl (op->r_id);
+
+  GNUNET_IDENTITY_ATTRIBUTE_serialize (attr,
+                       (char*)&sam[1]);
+
+  sam->attr_len = htons (attr_len);
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+
+}
+
+
+/**
+ * List all attributes for a local identity. 
+ * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
+ * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
+ *
+ * On error (disconnect), @a error_cb will be invoked.
+ * On normal completion, @a finish_cb proc will be
+ * invoked.
+ *
+ * @param h handle to the idp
+ * @param identity identity to access
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each attribute; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
+GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                               const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                               GNUNET_SCHEDULER_TaskCallback 
error_cb,
+                                               void *error_cb_cls,
+                                               
GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
+                                               void *proc_cls,
+                                               GNUNET_SCHEDULER_TaskCallback 
finish_cb,
+                                               void *finish_cb_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeIterationStartMessage *msg;
+  uint32_t rid;
+
+  rid = h->r_id_gen++;
+  it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator);
+  it->h = h;
+  it->error_cb = error_cb;
+  it->error_cb_cls = error_cb_cls;
+  it->finish_cb = finish_cb;
+  it->finish_cb_cls = finish_cb_cls;
+  it->proc = proc;
+  it->proc_cls = proc_cls;
+  it->r_id = rid;
+  it->identity = *identity;
+  GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
+                                    h->it_tail,
+                                    it);
+  env = GNUNET_MQ_msg (msg,
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  if (NULL == h->mq)
+    it->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return it;
+}
 
 
 /**
- * Destroy token
+ * Calls the record processor specified in 
#GNUNET_IDENTITY_PROVIDER_get_attributes_start
+ * for the next record.
  *
- * @param token the token
+ * @param it the iterator
  */
 void
-GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token 
*token)
+GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct 
GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+  struct AttributeIterationNextMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  env = GNUNET_MQ_msg (msg,
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT);
+  msg->id = htonl (it->r_id);
+  GNUNET_MQ_send (h->mq,
+                  env);
+}
+
+
+/**
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct 
GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeIterationStopMessage *msg;
+
+  if (NULL != h->mq)
+  {
+    env = GNUNET_MQ_msg (msg,
+                         
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP);
+    msg->id = htonl (it->r_id);
+    GNUNET_MQ_send (h->mq,
+                    env);
+  }
+  free_it (it);
+}
+
+
+/** TODO
+ * Issues a ticket to another identity. The identity may use
+ * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
+ * and retrieve the attributes specified in the AttributeList.
+ *
+ * @param h the identity provider to use
+ * @param iss the issuing identity
+ * @param rp the subject of the ticket (the relying party)
+ * @param attrs the attributes that the relying party is given access to
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle 
*h,
+                                       const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *iss,
+                                       const struct 
GNUNET_CRYPTO_EcdsaPublicKey *rp,
+                                       const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+                                       GNUNET_IDENTITY_PROVIDER_TicketCallback 
cb,
+                                       void *cb_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct IssueTicketMessage *tim;
+  size_t attr_len;
+
+  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+  op->h = h;
+  op->tr_cb = cb;
+  op->cls = cb_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
+  op->env = GNUNET_MQ_msg_extra (tim,
+                                 attr_len,
+                                 
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET);
+  tim->identity = *iss;
+  tim->rp = *rp;
+  tim->id = htonl (op->r_id);
+
+  GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
+                            (char*)&tim[1]);
+
+  tim->attr_len = htons (attr_len);
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+}
+
+/**
+ * Consumes an issued ticket. The ticket is persisted
+ * and used to retrieve identity information from the issuer
+ *
+ * @param h the identity provider to use
+ * @param identity the identity that is the subject of the issued ticket (the 
relying party)
+ * @param ticket the issued ticket to consume
+ * @param cb the callback to call
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_consume (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                         const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                         const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                         
GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
+                                         void *cb_cls)
 {
-  GNUNET_assert (NULL != token);
-  if (NULL != token->data)
-    GNUNET_free (token->data);
-  GNUNET_free (token);
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct ConsumeTicketMessage *ctm;
+
+  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+  op->h = h;
+  op->ar_cb = cb;
+  op->cls = cb_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  op->env = GNUNET_MQ_msg_extra (ctm,
+                                 sizeof (const struct 
GNUNET_IDENTITY_PROVIDER_Ticket),
+                                 
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET);
+  ctm->identity = *identity;
+  ctm->id = htonl (op->r_id);
+
+  GNUNET_memcpy ((char*)&ctm[1],
+                 ticket,
+                 sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket));
+
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+
 }
 
+
 /**
- * Returns string representation of token. A JSON-Web-Token.
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
  *
- * @param token the token
- * @return The JWT (must be freed)
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
  */
-char *
-GNUNET_IDENTITY_PROVIDER_token_to_string (const struct 
GNUNET_IDENTITY_PROVIDER_Token *token)
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                                 const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                                 GNUNET_SCHEDULER_TaskCallback 
error_cb,
+                                                 void *error_cb_cls,
+                                                 
GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
+                                                 void *proc_cls,
+                                                 GNUNET_SCHEDULER_TaskCallback 
finish_cb,
+                                                 void *finish_cb_cls)
 {
-  return GNUNET_strdup (token->data);
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketIterationStartMessage *msg;
+  uint32_t rid;
+
+  GNUNET_CRYPTO_ecdsa_key_get_public (identity,
+                                      &identity_pub);
+  rid = h->r_id_gen++;
+  it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
+  it->h = h;
+  it->error_cb = error_cb;
+  it->error_cb_cls = error_cb_cls;
+  it->finish_cb = finish_cb;
+  it->finish_cb_cls = finish_cb_cls;
+  it->tr_cb = proc;
+  it->cls = proc_cls;
+  it->r_id = rid;
+  GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
+                                    h->ticket_it_tail,
+                                    it);
+  env = GNUNET_MQ_msg (msg,
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = identity_pub;
+  msg->is_audience = htonl (GNUNET_NO);
+  if (NULL == h->mq)
+    it->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return it;
+
 }
 
+
 /**
- * Returns string representation of ticket. Base64-Encoded
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
  *
- * @param ticket the ticket
- * @return the Base64-Encoded ticket
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
  */
-char *
-GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                                    const struct 
GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                                                    
GNUNET_SCHEDULER_TaskCallback error_cb,
+                                                    void *error_cb_cls,
+                                                    
GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
+                                                    void *proc_cls,
+                                                    
GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                                    void *finish_cb_cls)
 {
-  return GNUNET_strdup (ticket->data);
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketIterationStartMessage *msg;
+  uint32_t rid;
+
+  rid = h->r_id_gen++;
+  it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator);
+  it->h = h;
+  it->error_cb = error_cb;
+  it->error_cb_cls = error_cb_cls;
+  it->finish_cb = finish_cb;
+  it->finish_cb_cls = finish_cb_cls;
+  it->tr_cb = proc;
+  it->cls = proc_cls;
+  it->r_id = rid;
+  GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head,
+                                    h->ticket_it_tail,
+                                    it);
+  env = GNUNET_MQ_msg (msg,
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  msg->is_audience = htonl (GNUNET_YES);
+  if (NULL == h->mq)
+    it->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return it;
+
+
 }
 
 /**
- * Created a ticket from a string (Base64 encoded ticket)
+ * Calls the record processor specified in 
#GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
+ * for the next record.
  *
- * @param input Base64 encoded ticket
- * @param ticket pointer where the ticket is stored
- * @return GNUNET_OK
+ * @param it the iterator
  */
-int
-GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input,
-                                           struct 
GNUNET_IDENTITY_PROVIDER_Ticket **ticket)
+void
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct 
GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
 {
-  *ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
-  (*ticket)->data = GNUNET_strdup (input);
-  return GNUNET_OK;
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+  struct TicketIterationNextMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  env = GNUNET_MQ_msg (msg,
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT);
+  msg->id = htonl (it->r_id);
+  GNUNET_MQ_send (h->mq,
+                  env);
 }
 
 
 /**
- * Destroys a ticket
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
  *
- * @param ticket the ticket to destroy
+ * @param it the iterator
  */
 void
-GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket 
*ticket)
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct 
GNUNET_IDENTITY_PROVIDER_TicketIterator *it)
 {
-  GNUNET_assert (NULL != ticket);
-  if (NULL != ticket->data)
-    GNUNET_free (ticket->data);
-  GNUNET_free (ticket);
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+  struct GNUNET_MQ_Envelope *env;
+  struct TicketIterationStopMessage *msg;
+
+  if (NULL != h->mq)
+  {
+    env = GNUNET_MQ_msg (msg,
+                         
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP);
+    msg->id = htonl (it->r_id);
+    GNUNET_MQ_send (h->mq,
+                    env);
+  }
+  GNUNET_free (it);
 }
 
+/**
+ * Revoked an issued ticket. The relying party will be unable to retrieve
+ * updated attributes.
+ *
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param ticket the ticket to revoke
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle 
*h,
+                                        const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                        const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                        
GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
+                                        void *cb_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct GNUNET_MQ_Envelope *env;
+  struct RevokeTicketMessage *msg;
+  uint32_t rid;
 
+  rid = h->r_id_gen++;
+  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+  op->h = h;
+  op->rvk_cb = cb;
+  op->cls = cb_cls;
+  op->r_id = rid;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  env = GNUNET_MQ_msg_extra (msg,
+                             sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
+                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  memcpy (&msg[1],
+          ticket,
+          sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
+  if (NULL == h->mq)
+    op->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return op;
+}
 
 
 
diff --git a/src/identity-provider/identity_token.c 
b/src/identity-provider/identity_token.c
deleted file mode 100644
index 31249840b..000000000
--- a/src/identity-provider/identity_token.c
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2015 GNUnet e.V.
-
-      GNUnet is free software; you can redistribute it and/or modify
-      it under the terms of the GNU General Public License as published
-      by the Free Software Foundation; either version 3, or (at your
-      option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      General Public License for more details.
-
-      You should have received a copy of the GNU General Public License
-      along with GNUnet; see the file COPYING.  If not, write to the
-      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-      Boston, MA 02110-1301, USA.
- */
-
-/**
- * @file identity-provider/identity_token.c
- * @brief helper library to manage identity tokens
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "identity_token.h"
-#include <jansson.h>
-#include <inttypes.h>
-
-#define JWT_ALG "alg"
-
-#define JWT_ALG_VALUE "ED512"
-
-#define JWT_TYP "typ"
-
-#define JWT_TYP_VALUE "jwt"
-
-/**
- * Crypto helper functions
- */
-
-static int
-create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
-                         struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
-                         struct GNUNET_CRYPTO_SymmetricInitializationVector 
*iv)
-{
-  struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
-
-  GNUNET_CRYPTO_hash_to_enc (new_key_hash,
-                             &new_key_hash_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", 
(char*)&new_key_hash_str);
-  static const char ctx_key[] = "gnuid-aes-ctx-key";
-  GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-                     new_key_hash, sizeof (struct GNUNET_HashCode),
-                     ctx_key, strlen (ctx_key),
-                     NULL, 0);
-  static const char ctx_iv[] = "gnuid-aes-ctx-iv";
-  GNUNET_CRYPTO_kdf (iv, sizeof (struct 
GNUNET_CRYPTO_SymmetricInitializationVector),
-                     new_key_hash, sizeof (struct GNUNET_HashCode),
-                     ctx_iv, strlen (ctx_iv),
-                     NULL, 0);
-  return GNUNET_OK;
-}
-
-
-
-/**
- * Decrypts data part from a token code
- */
-static int
-decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                   const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key,
-                   const char *cyphertext,
-                   size_t cyphertext_len,
-                   char **result_str)
-{
-  struct GNUNET_HashCode new_key_hash;
-  struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
-
-  char *str_buf = GNUNET_malloc (cyphertext_len);
-  size_t str_size;
-
-  //Calculate symmetric key from ecdh parameters
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key,
-                                                        ecdh_key,
-                                                        &new_key_hash));
-
-  create_sym_key_from_ecdh (&new_key_hash,
-                            &enc_key,
-                            &enc_iv);
-
-  str_size = GNUNET_CRYPTO_symmetric_decrypt (cyphertext,
-                                              cyphertext_len,
-                                              &enc_key,
-                                              &enc_iv,
-                                              str_buf);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Decrypted bytes: %zd Expected bytes: %zd\n",
-              str_size,
-              cyphertext_len);
-  if (-1 == str_size)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
-    GNUNET_free (str_buf);
-    return GNUNET_SYSERR;
-  }
-  *result_str = GNUNET_malloc (str_size+1);
-  GNUNET_memcpy (*result_str, str_buf, str_size);
-  (*result_str)[str_size] = '\0';
-  GNUNET_free (str_buf);
-  return GNUNET_OK;
-
-}
-
-/**
- * Decrypt string using pubkey and ECDHE
-*/
-static int
-decrypt_str_ecdhe2 (const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey,
-                    const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                    const char *ciphertext,
-                    size_t ciphertext_len,
-                    char **plaintext)
-{
-  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-  struct GNUNET_HashCode new_key_hash;
-
-  //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
-  *plaintext = GNUNET_malloc (ciphertext_len);
-
-  // Derived key K = H(eB)
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey,
-                                                        aud_key,
-                                                        &new_key_hash));
-  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
-  GNUNET_CRYPTO_symmetric_decrypt (ciphertext,
-                                   ciphertext_len,
-                                   &skey, &iv,
-                                   *plaintext);
-  return GNUNET_OK;
-}
-
-
-/**
- * Encrypt string using pubkey and ECDHE
- * Returns ECDHE pubkey to be used for decryption
- */
-static int
-encrypt_str_ecdhe (const char *plaintext,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
-                   char **cyphertext,
-                   struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
-                   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey)
-{
-  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-  struct GNUNET_HashCode new_key_hash;
-  ssize_t enc_size;
-
-  // ECDH keypair E = eG
-  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
-  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
-                                      ecdh_pubkey);
-
-  //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
-  *cyphertext = GNUNET_malloc (strlen (plaintext));
-
-  // Derived key K = H(eB)
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
-                                                        pub_key,
-                                                        &new_key_hash));
-  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting string %s\n (len=%zd)",
-              plaintext,
-              strlen (plaintext));
-  enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext,
-                                              strlen (plaintext),
-                                              &skey, &iv,
-                                              *cyphertext);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted (len=%zd)", enc_size);
-  return GNUNET_OK;
-}
-
-
-/**
- * Identity Token API
- */
-
-
-/**
- * Create an Identity Token
- *
- * @param type the JSON API resource type
- * @param id the JSON API resource id
- * @return a new JSON API resource or NULL on error.
- */
-struct IdentityToken*
-token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
-                                       const struct 
GNUNET_CRYPTO_EcdsaPublicKey* aud)
-{
-  struct IdentityToken *token;
-  char* audience;
-  char* issuer;
-
-  issuer = GNUNET_STRINGS_data_to_string_alloc (iss,
-                                                sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-  audience = GNUNET_STRINGS_data_to_string_alloc (aud,
-                                                  sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-
-  token = GNUNET_malloc (sizeof (struct IdentityToken));
-  token_add_attr (token, "iss", issuer);
-  token_add_attr (token, "aud", audience);
-  token_add_attr (token, "sub", issuer);
-  token->aud_key = *aud;
-  GNUNET_free (issuer);
-  GNUNET_free (audience);
-  return token;
-}
-
-void
-token_destroy (struct IdentityToken *token)
-{
-  struct TokenAttr *attr;
-  struct TokenAttr *tmp_attr;
-  struct TokenAttrValue *val;
-  struct TokenAttrValue *tmp_val;
-
-  for (attr = token->attr_head; NULL != attr;)
-  {
-    tmp_attr = attr->next;
-    GNUNET_CONTAINER_DLL_remove (token->attr_head,
-                                 token->attr_tail,
-                                 attr);
-    for (val = attr->val_head; NULL != val;)
-    {
-      tmp_val = val->next;
-      GNUNET_CONTAINER_DLL_remove (attr->val_head,
-                                   attr->val_tail,
-                                   val);
-      if (NULL != val->value)
-        GNUNET_free (val->value);
-      GNUNET_free (val);
-      val = tmp_val;
-    }
-    GNUNET_free (attr->name);
-    GNUNET_free (attr);
-    attr = tmp_attr;
-  }
-
-  
-  GNUNET_free (token);
-}
-
-void
-token_add_attr (struct IdentityToken *token,
-                const char* key,
-                const char* value)
-{
-  struct TokenAttr *attr;
-  struct TokenAttrValue *new_val;
-  GNUNET_assert (NULL != token);
-
-  new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
-  new_val->value = GNUNET_strdup (value);
-  for (attr = token->attr_head; NULL != attr; attr = attr->next)
-  {
-    if (0 == strcmp (key, attr->name))
-      break;
-  }
-
-  if (NULL == attr)
-  {
-    attr = GNUNET_malloc (sizeof (struct TokenAttr));
-    attr->name = GNUNET_strdup (key);
-    GNUNET_CONTAINER_DLL_insert (token->attr_head,
-                                 token->attr_tail,
-                                 attr);
-  }
-
-  GNUNET_CONTAINER_DLL_insert (attr->val_head,
-                               attr->val_tail,
-                               new_val);
-}
-
-void
-token_add_attr_int (struct IdentityToken *token,
-                    const char* key,
-                    uint64_t value)
-{
-  struct TokenAttr *attr;
-  struct TokenAttrValue *new_val;
-  GNUNET_assert (NULL != token);
-
-  new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
-  new_val->int_value = value;
-  for (attr = token->attr_head; NULL != attr; attr = attr->next)
-  {
-    if (0 == strcmp (key, attr->name))
-      break;
-  }
-
-  if (NULL == attr)
-  {
-    attr = GNUNET_malloc (sizeof (struct TokenAttr));
-    attr->name = GNUNET_strdup (key);
-    GNUNET_CONTAINER_DLL_insert (token->attr_head,
-                                 token->attr_tail,
-                                 attr);
-  }
-
-  GNUNET_CONTAINER_DLL_insert (attr->val_head,
-                               attr->val_tail,
-                               new_val);
-}
-
-static void
-parse_json_payload(const char* payload_base64,
-                   struct IdentityToken *token) 
-{
-  const char *key;
-  const json_t *value;
-  const json_t *arr_value;
-  char *payload;
-  int idx;
-  json_t *payload_json;
-  json_error_t err_json;
-
-  GNUNET_STRINGS_base64_decode (payload_base64,
-                                strlen (payload_base64),
-                                &payload);
-  //TODO signature and aud key
-  payload_json = json_loads (payload, JSON_DECODE_ANY, &err_json);
-
-  json_object_foreach (payload_json, key, value)
-  {
-    if (json_is_array (value))
-    {
-      json_array_foreach (value, idx, arr_value)
-      {
-        if (json_is_integer (arr_value))
-          token_add_attr_int (token, key,
-                              json_integer_value (arr_value));
-        else
-          token_add_attr (token,
-                          key,
-                          json_string_value (arr_value));
-      }
-    } else {
-      if (json_is_integer (value))
-        token_add_attr_int (token, key,
-                            json_integer_value (value));
-      else
-        token_add_attr (token, key, json_string_value (value));
-    }
-  }
-
-  json_decref (payload_json);
-  GNUNET_free (payload);
-}
-
-int
-token_parse2 (const char* raw_data,
-              const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
-              const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-              struct IdentityToken **result)
-{
-  char *enc_token_str;
-  char *tmp_buf;
-  char *token_str;
-  char *enc_token;
-  char *payload_base64;
-  size_t enc_token_len;
-
-  GNUNET_asprintf (&tmp_buf, "%s", raw_data);
-  strtok (tmp_buf, ",");
-  enc_token_str = strtok (NULL, ",");
-
-  enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
-                                                strlen (enc_token_str),
-                                                &enc_token);
-  if (GNUNET_OK != decrypt_str_ecdhe2 (priv_key,
-                                       aud_key,
-                                       enc_token,
-                                       enc_token_len,
-                                       &token_str))
-  {
-    GNUNET_free (tmp_buf);
-    GNUNET_free (enc_token);
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_assert (NULL != strtok (token_str, "."));
-  payload_base64 = strtok (NULL, ".");
-
-  *result = GNUNET_malloc (sizeof (struct IdentityToken));
-  parse_json_payload (payload_base64, *result);
-
-  (*result)->aud_key =  *aud_key;
-  GNUNET_free (enc_token);
-  GNUNET_free (token_str);
-  GNUNET_free (tmp_buf);
-  return GNUNET_OK;
-}
-
-int
-token_parse (const char* raw_data,
-             const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-             struct IdentityToken **result)
-{
-  char *ecdh_pubkey_str;
-  char *enc_token_str;
-  char *tmp_buf;
-  char *token_str;
-  char *enc_token;
-  char *payload_base64;
-  size_t enc_token_len;
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
-  GNUNET_asprintf (&tmp_buf, "%s", raw_data);
-  ecdh_pubkey_str = strtok (tmp_buf, ",");
-  enc_token_str = strtok (NULL, ",");
-  
-  GNUNET_assert (NULL != ecdh_pubkey_str);
-  GNUNET_assert (NULL != enc_token_str);
-
-  GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
-                                 strlen (ecdh_pubkey_str),
-                                 &ecdh_pubkey,
-                                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
-                                                strlen (enc_token_str),
-                                                &enc_token);
-  if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
-                                      &ecdh_pubkey,
-                                      enc_token,
-                                      enc_token_len,
-                                      &token_str))
-  {
-    GNUNET_free (tmp_buf);
-    GNUNET_free (enc_token);
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_assert (NULL != strtok (token_str, "."));
-  payload_base64 = strtok (NULL, ".");
-
-  *result = GNUNET_malloc (sizeof (struct IdentityToken));
-  parse_json_payload (payload_base64, *result);
-
-  GNUNET_free (enc_token);
-  GNUNET_free (token_str);
-  GNUNET_free (tmp_buf);
-  return GNUNET_OK;
-}
-
-static char*
-create_json_payload (const struct IdentityToken *token)
-{
-  struct TokenAttr *attr;
-  struct TokenAttrValue *val;
-  json_t *root;
-  char *json_str;
-
-  root = json_object();
-  for (attr = token->attr_head; NULL != attr; attr = attr->next)
-  {
-    for (val = attr->val_head; NULL != val; val = val->next)
-    {
-      if (NULL != val->value)
-      {
-        json_object_set_new (root,
-                             attr->name,
-                             json_string (val->value)); 
-      } else {
-        json_object_set_new (root,
-                             attr->name,
-                             json_integer (val->int_value));
-      }
-    }
-  }
-  json_str = json_dumps (root, JSON_INDENT(1));
-  json_decref (root);
-  return json_str;
-}
-
-static char*
-create_json_header(void)
-{
-  json_t *root;
-  char *json_str;
-
-  root = json_object ();
-  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
-  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
-
-  json_str = json_dumps (root, JSON_INDENT(1));
-  json_decref (root);
-  return json_str;
-}
-
-int
-token_to_string (const struct IdentityToken *token,
-                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                 char **result)
-{
-  char *payload_str;
-  char *header_str;
-  char *payload_base64;
-  char *header_base64;
-  char *padding;
-  char *signature_target;
-  char *signature_str;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  header_str = create_json_header();
-  GNUNET_STRINGS_base64_encode (header_str,
-                                strlen (header_str),
-                                &header_base64);
-  //Remove GNUNET padding of base64
-  padding = strtok(header_base64, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  payload_str = create_json_payload (token);
-  GNUNET_STRINGS_base64_encode (payload_str,
-                                strlen (payload_str),
-                                &payload_base64);
-
-  //Remove GNUNET padding of base64
-  padding = strtok(payload_base64, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  GNUNET_asprintf (&signature_target, "%s,%s", header_base64, payload_base64);
-  purpose =
-    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-                   strlen (signature_target));
-  purpose->size =
-    htonl (strlen (signature_target) + sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose));
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
-  GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
-                                             purpose,
-                                             (struct 
GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
-  {
-    GNUNET_free (signature_target);
-    GNUNET_free (payload_str);
-    GNUNET_free (payload_base64);
-    GNUNET_free (header_base64);
-    GNUNET_free (purpose);
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_STRINGS_base64_encode ((const char*)&token->signature,
-                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
-                                &signature_str);
-  GNUNET_asprintf (result, "%s.%s.%s",
-                   header_base64, payload_base64, signature_str);
-  GNUNET_free (signature_target);
-  GNUNET_free (payload_str);
-  GNUNET_free (header_str);
-  GNUNET_free (signature_str);
-  GNUNET_free (payload_base64);
-  GNUNET_free (header_base64);
-  GNUNET_free (purpose);
-  return GNUNET_OK;
-}
-
-int
-token_serialize (const struct IdentityToken *token,
-                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
-                 char **result)
-{
-  char *token_str;
-  char *enc_token;
-  char *dh_key_str;
-  char *enc_token_base64;
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
-  GNUNET_assert (GNUNET_OK == token_to_string (token,
-                                               priv_key,
-                                               &token_str));
-
-  GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
-                                                 &token->aud_key,
-                                                 &enc_token,
-                                                 ecdh_privkey,
-                                                 &ecdh_pubkey));
-  GNUNET_STRINGS_base64_encode (enc_token,
-                                strlen (token_str),
-                                &enc_token_base64);
-  dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey,
-                                                    sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_asprintf (result, "%s,%s", dh_key_str, enc_token_base64);
-  GNUNET_free (dh_key_str);
-  GNUNET_free (enc_token_base64);
-  GNUNET_free (enc_token);
-  GNUNET_free (token_str);
-  return GNUNET_OK;
-}
-
-struct TokenTicketPayload*
-ticket_payload_create (uint64_t nonce,
-                       const struct GNUNET_CRYPTO_EcdsaPublicKey* 
identity_pkey,
-                       const char* lbl_str)
-{
-  struct TokenTicketPayload* payload;
-
-  payload = GNUNET_malloc (sizeof (struct TokenTicketPayload));
-  payload->nonce = nonce;
-  payload->identity_key = *identity_pkey;
-  GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
-  return payload;
-}
-
-void
-ticket_payload_destroy (struct TokenTicketPayload* payload)
-{
-  if (NULL != payload->label)
-    GNUNET_free (payload->label);
-  GNUNET_free (payload);
-}
-
-void
-ticket_payload_serialize (struct TokenTicketPayload *payload,
-                          char **result)
-{
-  char* identity_key_str;
-
-  identity_key_str = GNUNET_STRINGS_data_to_string_alloc 
(&payload->identity_key,
-                                                          sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-
-  GNUNET_asprintf (result, 
-                   "{\"nonce\": \"%"SCNu64"\",\"identity\": \"%s\",\"label\": 
\"%s\"}",
-                   payload->nonce, identity_key_str, payload->label);
-  GNUNET_free (identity_key_str);
-
-}
-
-
-/**
- * Create the token code
- * The data is encrypted with a share ECDH derived secret using B (aud_key)
- * and e (ecdh_privkey)
- * The ticket also contains E (ecdh_pubkey) and a signature over the
- * data and E
- */
-struct TokenTicket*
-ticket_create (uint64_t nonce,
-               const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
-               const char* lbl_str,
-               const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
-{
-  struct TokenTicket *ticket;
-  struct TokenTicketPayload *code_payload;
-
-  ticket = GNUNET_malloc (sizeof (struct TokenTicket));
-  code_payload = ticket_payload_create (nonce,
-                                        identity_pkey,
-                                        lbl_str);
-  ticket->aud_key = *aud_key;
-  ticket->payload = code_payload;
-
-
-  return ticket;
-}
-
-void
-ticket_destroy (struct TokenTicket *ticket)
-{
-  ticket_payload_destroy (ticket->payload);
-  GNUNET_free (ticket);
-}
-
-int
-ticket_serialize (struct TokenTicket *ticket,
-                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                  char **result)
-{
-  char *code_payload_str;
-  char *enc_ticket_payload;
-  char *ticket_payload_str;
-  char *ticket_sig_str;
-  char *ticket_str;
-  char *dh_key_str;
-  char *write_ptr;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-
-  ticket_payload_serialize (ticket->payload,
-                            &code_payload_str);
-
-  GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (code_payload_str,
-                                                 &ticket->aud_key,
-                                                 &enc_ticket_payload,
-                                                 &ecdhe_privkey,
-                                                 &ticket->ecdh_pubkey));
-
-  GNUNET_free (ecdhe_privkey);
-
-  purpose = 
-    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
-                   sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
-                   strlen (code_payload_str)); // E_K (code_str)
-  purpose->size = 
-    htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
-           strlen (code_payload_str));
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
-  write_ptr = (char*) &purpose[1];
-  GNUNET_memcpy (write_ptr,
-          &ticket->ecdh_pubkey,
-          sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
-  GNUNET_memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
-                                                        purpose,
-                                                        &ticket->signature));
-  GNUNET_STRINGS_base64_encode (enc_ticket_payload,
-                                strlen (code_payload_str),
-                                &ticket_payload_str);
-  ticket_sig_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->signature,
-                                                        sizeof (struct 
GNUNET_CRYPTO_EcdsaSignature));
-
-  dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
-                                                    sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s to encrypt\n", 
dh_key_str);
-  GNUNET_asprintf (&ticket_str, "{\"data\": \"%s\", \"ecdh\": \"%s\", 
\"signature\": \"%s\"}",
-                   ticket_payload_str, dh_key_str, ticket_sig_str);
-  GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
-  GNUNET_free (dh_key_str);
-  GNUNET_free (purpose);
-  GNUNET_free (ticket_str);
-  GNUNET_free (ticket_sig_str);
-  GNUNET_free (code_payload_str);
-  GNUNET_free (enc_ticket_payload);
-  GNUNET_free (ticket_payload_str);
-  return GNUNET_OK;
-}
-
-int
-ticket_payload_parse(const char *raw_data,
-                     ssize_t data_len,
-                     const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                     const struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey,
-                     struct TokenTicketPayload **result)
-{
-  const char* label_str;
-  const char* nonce_str;
-  const char* identity_key_str;
-
-  json_t *root;
-  json_t *label_json;
-  json_t *identity_json;
-  json_t *nonce_json;
-  json_error_t err_json;
-  char* data_str;
-  uint64_t nonce;
-  struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
-
-  if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
-                                      ecdhe_pkey,
-                                      raw_data,
-                                      data_len,
-                                      &data_str))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Data decryption failed\n");
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data: %s\n", data_str);
-  root = json_loads (data_str, JSON_DECODE_ANY, &err_json);
-  if (!root)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing data: %s\n", err_json.text);
-    GNUNET_free (data_str);
-    return GNUNET_SYSERR;
-  }
-
-  identity_json = json_object_get (root, "identity");
-  if (!json_is_string (identity_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing data: %s\n", err_json.text);
-    json_decref (root);
-    GNUNET_free (data_str);
-    return GNUNET_SYSERR;
-  }
-  identity_key_str = json_string_value (identity_json);
-  GNUNET_STRINGS_string_to_data (identity_key_str,
-                                 strlen (identity_key_str),
-                                 &id_pkey,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-
-  label_json = json_object_get (root, "label");
-  if (!json_is_string (label_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing data: %s\n", err_json.text);
-    json_decref (root);
-    GNUNET_free (data_str);
-    return GNUNET_SYSERR;
-  }
-
-  label_str = json_string_value (label_json);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found label: %s\n", label_str);
-
-  nonce_json = json_object_get (root, "nonce");
-  if (!json_is_string (label_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing data: %s\n", err_json.text);
-    json_decref (root);
-    GNUNET_free (data_str);
-    return GNUNET_SYSERR;
-  }
-
-  nonce_str = json_string_value (nonce_json);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found nonce: %s\n", nonce_str);
-  
-  GNUNET_assert (0 != sscanf (nonce_str, "%"SCNu64, &nonce));
-
-  *result = ticket_payload_create (nonce,
-                                   (const struct 
GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
-                                   label_str);
-  GNUNET_free (data_str);
-  json_decref (root);
-  return GNUNET_OK;
-
-}
-
-int
-ticket_parse (const char *raw_data,
-              const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-              struct TokenTicket **result)
-{
-  const char* enc_data_str;
-  const char* ecdh_enc_str;
-  const char* signature_enc_str;
-
-  json_t *root;
-  json_t *signature_json;
-  json_t *ecdh_json;
-  json_t *enc_data_json;
-  json_error_t err_json;
-  char* enc_data;
-  char* ticket_decoded;
-  char* write_ptr;
-  size_t enc_data_len;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  struct TokenTicket *ticket;
-  struct TokenTicketPayload *ticket_payload;
-
-  ticket_decoded = NULL;
-  GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket: %s\n", ticket_decoded);
-  root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
-  if (!root)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "%s\n", err_json.text);
-    return GNUNET_SYSERR;
-  }
-
-  signature_json = json_object_get (root, "signature");
-  ecdh_json = json_object_get (root, "ecdh");
-  enc_data_json = json_object_get (root, "data");
-
-  signature_enc_str = json_string_value (signature_json);
-  ecdh_enc_str = json_string_value (ecdh_json);
-  enc_data_str = json_string_value (enc_data_json);
-
-  ticket = GNUNET_malloc (sizeof (struct TokenTicket));
-
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str,
-                                                  strlen (ecdh_enc_str),
-                                                  &ticket->ecdh_pubkey,
-                                                  sizeof  (struct 
GNUNET_CRYPTO_EcdhePublicKey)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in data\n", 
ecdh_enc_str);
-    json_decref (root);
-    GNUNET_free (ticket);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s for data 
decryption\n", ecdh_enc_str);
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
-                                                  strlen (signature_enc_str),
-                                                  &ticket->signature,
-                                                  sizeof (struct 
GNUNET_CRYPTO_EcdsaSignature)))
-  {
-    json_decref (root);
-    GNUNET_free (ticket_decoded);
-    GNUNET_free (ticket);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in data\n");
-    return GNUNET_SYSERR;
-  }
-
-  enc_data_len = GNUNET_STRINGS_base64_decode (enc_data_str,
-                                               strlen (enc_data_str),
-                                               &enc_data);
-
-
-  if (GNUNET_OK != ticket_payload_parse (enc_data,
-                                         enc_data_len,
-                                         priv_key,
-                                         (const struct 
GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
-                                         &ticket_payload))
-  {
-    json_decref (root);
-    GNUNET_free (enc_data);
-    GNUNET_free (ticket_decoded);
-    GNUNET_free (ticket);
-    return GNUNET_SYSERR;
-  }
-
-  ticket->payload = ticket_payload;
-  purpose = 
-    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
-                   sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
-                   enc_data_len); // E_K (code_str)
-  purpose->size = 
-    htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
-           enc_data_len);
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
-  write_ptr = (char*) &purpose[1];
-  GNUNET_memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey));
-  write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
-  GNUNET_memcpy (write_ptr, enc_data, enc_data_len);
-
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify 
(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
-                                               purpose,
-                                               &ticket->signature,
-                                               &ticket_payload->identity_key))
-  {
-    ticket_destroy (ticket);
-    GNUNET_free (ticket_decoded);
-    json_decref (root);
-    GNUNET_free (purpose);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error verifying signature for ticket\n");
-    return GNUNET_SYSERR;
-  }
-  *result = ticket;
-  GNUNET_free (purpose);
-
-  GNUNET_free (enc_data);
-  GNUNET_free (ticket_decoded);
-  json_decref (root);
-  return GNUNET_OK;
-
-}
-
-
-
-/* end of identity_token.c */
diff --git a/src/identity-provider/identity_token.h 
b/src/identity-provider/identity_token.h
deleted file mode 100644
index 7ded6662e..000000000
--- a/src/identity-provider/identity_token.h
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published
-   by the Free Software Foundation; either version 3, or (at your
-   option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GNUnet; see the file COPYING.  If not, write to the
-   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.
-   */
-/**
- * @author Martin Schanzenbach
- * @file identity-provider/identity_token.h
- * @brief GNUnet Identity Provider library
- *
- */
-#ifndef IDENTITY_TOKEN_H
-#define IDENTITY_TOKEN_H
-
-#include "gnunet_crypto_lib.h"
-#include <jansson.h>
-
-struct IdentityToken
-{
-  /**
-   * DLL
-   */
-  struct TokenAttr *attr_head;
-
-  /**
-   * DLL
-   */
-  struct TokenAttr *attr_tail;
-
-  /**
-   * Token Signature
-   */
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-  
-  /**
-   * Audience Pubkey
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
-};
-
-struct TokenAttr
-{
-  /**
-   * DLL
-   */
-  struct TokenAttr *next;
-
-  /**
-   * DLL
-   */
-  struct TokenAttr *prev;
-
-  /**
-   * Attribute name
-   */
-  char *name;
-
-  /**
-   * Attribute value DLL
-   */
-  struct TokenAttrValue *val_head;
-
-  /**
-   * Attribute value DLL
-   */
-  struct TokenAttrValue *val_tail;
-
-};
-
-struct TokenAttrValue
-{
-  /**
-   * DLL
-   */
-  struct TokenAttrValue *next;
-
-  /**
-   * DLL
-   */
-  struct TokenAttrValue *prev;
-
-  /**
-   * Attribute value
-   */
-  char *value;
-
-  /**
-   * Attribute int value
-   * used if NULL == value
-   */
-  uint64_t int_value;
-};
-
-struct TokenTicketPayload
-{
-  /**
-   * Nonce
-   */
-  uint64_t nonce;
-
-  /**
-   * Label
-   */
-  char *label;
-
-  /**
-   * Issuing Identity
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity_key;
-};
-
-
-struct TokenTicket
-{
-  /**
-   * Meta info
-   */
-  struct TokenTicketPayload *payload;
-
-  /**
-   * ECDH Pubkey
-   */
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-
-  /**
-   * Signature
-   */
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-
-  /**
-   * Target identity
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
-};
-
-
-
-/**
- * Create an identity token
- *
- * @param iss the issuer string for the token
- * @param aud the audience of the token
- *
- * @return a new token
- */
-struct IdentityToken*
-token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *iss,
-                                       const struct 
GNUNET_CRYPTO_EcdsaPublicKey* aud);
-
-/**
- * Destroy an identity token
- *
- * @param token the token to destroy
- */
-void
-token_destroy (struct IdentityToken*token);
-
-/**
- * Add a new key value pair to the token
- * 
- * @param token the token to modify
- * @param key the key
- * @param value the value
- */
-void
-token_add_attr (struct IdentityToken *token,
-                const char* key,
-                const char* value);
-
-/**
- * Add a new key value pair to the token
- * 
- * @param token the token to modify
- * @param key the key
- * @param value the value
- */
-void
-token_add_attr_int (struct IdentityToken *token,
-                      const char* key,
-                      uint64_t value);
-
-
-
-/**
- * Add a value to a TokenAttribute
- *
- * @param attr the token attribute
- * @param value value to add
- */
-  void
-  token_attr_add_value (const struct TokenAttr *attr,
-                        const char *value);
-
-/**
- * Add a new key value pair to the token with the value as json
- *
- * @param the token to modify
- * @param key the key
- * @param value the value
- *
- */
-  void
-  token_add_json (const struct IdentityToken *token,
-                  const char* key,
-                  json_t* value);
-
-/**
- * Serialize a token. The token will be signed and base64 according to the
- * JWT format. The signature is base32-encoded ECDSA.
- * The resulting JWT is encrypted using 
- * ECDHE for the audience and Base64
- * encoded in result. The audience requires the ECDHE public key P 
- * to decrypt the token T. The key P is included in the result and prepended
- * before the token
- *
- * @param token the token to serialize
- * @param priv_key the private key used to sign the token
- * @param ecdhe_privkey the ECDHE private key used to encrypt the token
- * @param result P,Base64(E(T))
- *
- * @return GNUNET_OK on success
- */
-  int 
-  token_serialize (const struct IdentityToken*token,
-                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                   struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
-                   char **result);
-
-/**
- * Parses the serialized token and returns a token
- *
- * @param data the serialized token
- * @param priv_key the private key of the audience
- * @param result the token
- *
- * @return GNUNET_OK on success
- */
-               int
-               token_parse (const char* data,
-                            const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*priv_key,
-                            struct IdentityToken **result);
-
-/**
- * Parses the serialized token and returns a token
- * This variant is intended for the party that issued the token and also
- * wants to decrypt the serialized token.
- *
- * @param data the serialized token
- * @param priv_key the private (!) ECDHE key
- * @param aud_key the identity of the audience
- * @param result the token
- *
- * @return GNUNET_OK on success
- */
-int
-token_parse2 (const char* data,
-              const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
-              const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-              struct IdentityToken **result);
-
-
-/**
- *
- * Returns a JWT-string representation of the token
- *
- * @param token the token
- * @param priv_key the private key used to sign the JWT
- * @param result the JWT
- *
- * @return GNUNET_OK on success
- */
-  int
-  token_to_string (const struct IdentityToken *token,
-                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                   char **result);
-
-/**
- *
- * Creates a ticket that can be exchanged by the audience for 
- * the token. The token must be placed under the label
- *
- * @param nonce nonce provided by the audience that requested the ticket
- * @param iss_pkey the issuer pubkey used to sign the ticket
- * @param label the label encoded in the ticket
- * @param aud_ley the audience pubkey used to encrypt the ticket payload
- *
- * @return the ticket
- */
-struct TokenTicket*
-ticket_create (uint64_t nonce,
-               const struct GNUNET_CRYPTO_EcdsaPublicKey* iss_pkey,
-               const char* lbl_str,
-               const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key);
-
-/**
- * Serialize a ticket. Returns the Base64 representation of the ticket.
- * Format: Base64( { payload: E(Payload), ecdhe: K, signature: signature } )
- *
- * @param ticket the ticket to serialize
- * @param priv_key the issuer private key to sign the ticket payload
- * @param result the serialized ticket
- *
- * @return GNUNET_OK on success
- */
-  int
-  ticket_serialize (struct TokenTicket *ticket,
-                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-                    char **result);
-
-/**
- * Destroys a ticket
- *
- * @param the ticket to destroy
- */
-void
-ticket_destroy (struct TokenTicket *ticket);
-
-/**
- * Parses a serialized ticket
- *
- * @param data the serialized ticket
- * @param priv_key the audience private key
- * @param ticket the ticket
- *
- * @return GNUNET_OK on success
- */
-int
-ticket_parse (const char* raw_data,
-              const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
-              struct TokenTicket **ticket);
-
-#endif
diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c
new file mode 100644
index 000000000..2f1e3240b
--- /dev/null
+++ b/src/identity-provider/jwt.c
@@ -0,0 +1,180 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published
+      by the Free Software Foundation; either version 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+      Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file identity-provider/jwt.c
+ * @brief helper library for JSON-Web-Tokens
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_identity_attribute_lib.h"
+#include <jansson.h>
+
+
+#define JWT_ALG "alg"
+
+/*TODO is this the correct way to define new algs? */
+#define JWT_ALG_VALUE "ED512"
+
+#define JWT_TYP "typ"
+
+#define JWT_TYP_VALUE "jwt"
+
+static char*
+create_jwt_header(void)
+{
+  json_t *root;
+  char *json_str;
+
+  root = json_object ();
+  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
+  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
+
+  json_str = json_dumps (root, JSON_INDENT(1));
+  json_decref (root);
+  return json_str;
+}
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param sub_key the public of the subject
+ * @param attrs the attribute list
+ * @param priv_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char*
+jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                                                const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+                                                const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *priv_key)
+{
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_CRYPTO_EcdsaPublicKey iss_key;
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  char* audience;
+  char* issuer;
+  char* header;
+  char* padding;
+  char* body_str;
+  char* result;
+  char* header_base64;
+  char* body_base64;
+  char* signature_target;
+  char* signature_base64;
+  char* attr_val_str;
+  json_t* body;
+
+  GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &iss_key);
+  /* TODO maybe we should use a local identity here */
+  issuer = GNUNET_STRINGS_data_to_string_alloc (&iss_key,
+                                                sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+  audience = GNUNET_STRINGS_data_to_string_alloc (sub_key,
+                                                  sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+  header = create_jwt_header ();
+  body = json_object ();
+  /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */
+  json_object_set_new (body,
+                       "iss", json_string (issuer));
+  json_object_set_new (body,
+                       "sub", json_string (issuer));
+  /* TODO what should be in here exactly? */
+  json_object_set_new (body,
+                       "aud", json_string (audience));
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    /**
+     * TODO here we should have a function that
+     * calls the Attribute plugins to create a
+     * json representation for its value
+     */
+    attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type,
+                                                              le->claim->data,
+                                                              
le->claim->data_size);
+    json_object_set_new (body,
+                         le->claim->name,
+                         json_string (attr_val_str));
+    GNUNET_free (attr_val_str);
+  }
+  body_str = json_dumps (body, JSON_INDENT(0));
+  json_decref (body);
+
+  GNUNET_STRINGS_base64_encode (header,
+                                strlen (header),
+                                &header_base64);
+  //Remove GNUNET padding of base64
+  padding = strtok(header_base64, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  GNUNET_STRINGS_base64_encode (body_str,
+                                strlen (body_str),
+                                &body_base64);
+
+  //Remove GNUNET padding of base64
+  padding = strtok(body_base64, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  GNUNET_free (issuer);
+  GNUNET_free (audience);
+
+  /**
+   * TODO
+   * Creating the JWT signature. This might not be
+   * standards compliant, check.
+   */
+  GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
+
+  purpose =
+    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+                   strlen (signature_target));
+  purpose->size =
+    htonl (strlen (signature_target) + sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose));
+  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
+  GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
+                                             purpose,
+                                             (struct 
GNUNET_CRYPTO_EcdsaSignature *)&signature))
+  {
+    GNUNET_free (signature_target);
+    GNUNET_free (body_str);
+    GNUNET_free (body_base64);
+    GNUNET_free (header_base64);
+    GNUNET_free (purpose);
+    return NULL;
+  }
+  GNUNET_STRINGS_base64_encode ((const char*)&signature,
+                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+                                &signature_base64);
+  GNUNET_asprintf (&result, "%s.%s.%s",
+                   header_base64, body_base64, signature_base64);
+
+  GNUNET_free (signature_target);
+  GNUNET_free (header);
+  GNUNET_free (body_str);
+  GNUNET_free (signature_base64);
+  GNUNET_free (body_base64);
+  GNUNET_free (header_base64);
+  GNUNET_free (purpose);
+  return result;
+}
diff --git a/src/identity/plugin_gnsrecord_identity.c 
b/src/identity-provider/plugin_gnsrecord_identity_provider.c
similarity index 81%
rename from src/identity/plugin_gnsrecord_identity.c
rename to src/identity-provider/plugin_gnsrecord_identity_provider.c
index c26c04074..6ed0b0852 100644
--- a/src/identity/plugin_gnsrecord_identity.c
+++ b/src/identity-provider/plugin_gnsrecord_identity_provider.c
@@ -19,9 +19,9 @@
 */
 
 /**
- * @file identity/plugin_gnsrecord_identity.c
+ * @file identity-provider/plugin_gnsrecord_identity_provider.c
  * @brief gnsrecord plugin to provide the API for identity records
- * @author Christian Grothoff
+ * @author Martin Schanzenbach
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -54,9 +54,13 @@ value_to_string (void *cls,
   switch (type)
   {
     case GNUNET_GNSRECORD_TYPE_ID_ATTR:
-    case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
+      return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
+    case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED
       return GNUNET_strndup (data, data_size);
-    case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
+    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+      return GNUNET_STRINGS_data_to_string_alloc (data, data_size); 
+    case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED
         ecdhe_privkey = data;
         audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
         scopes =  (char*) audience_pubkey+(sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
@@ -106,12 +110,22 @@ string_to_value (void *cls,
   switch (type)
   {
     case GNUNET_GNSRECORD_TYPE_ID_ATTR:
+      return GNUNET_STRINGS_string_to_data (s,
+                                            strlen (s),
+                                            *data,
+                                            *data_size);
     case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
       *data = GNUNET_strdup (s);
       *data_size = strlen (s);
       return GNUNET_OK;
+    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+      return GNUNET_STRINGS_string_to_data (s,
+                                            strlen (s),
+                                            *data,
+                                            *data_size);
     case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
-            tmp_tok = GNUNET_strdup (s);
+      tmp_tok = GNUNET_strdup (s);
       ecdhe_str = strtok (tmp_tok, ";");
       if (NULL == ecdhe_str)
       {
@@ -160,15 +174,17 @@ string_to_value (void *cls,
  * Mapping of record type numbers to human-readable
  * record type names.
  */
-        static struct {
-          const char *name;
-          uint32_t number;
-        } name_map[] = {
-          { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
-          { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
-          { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
-          { NULL, UINT32_MAX }
-        };
+static struct {
+  const char *name;
+  uint32_t number;
+} name_map[] = {
+  { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
+  { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
+  { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY },
+  { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER },
+  { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
+  { NULL, UINT32_MAX }
+};
 
 
 /**
@@ -220,7 +236,7 @@ number_to_typename (void *cls,
  * @return the exported block API
  */
 void *
-libgnunet_plugin_gnsrecord_identity_init (void *cls)
+libgnunet_plugin_gnsrecord_identity_provider_init (void *cls)
 {
   struct GNUNET_GNSRECORD_PluginFunctions *api;
 
@@ -240,7 +256,7 @@ libgnunet_plugin_gnsrecord_identity_init (void *cls)
  * @return NULL
  */
 void *
-libgnunet_plugin_gnsrecord_identity_done (void *cls)
+libgnunet_plugin_gnsrecord_identity_provider_done (void *cls)
 {
   struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
 
diff --git a/src/namestore/plugin_namestore_sqlite.c 
b/src/identity-provider/plugin_identity_provider_sqlite.c
similarity index 50%
copy from src/namestore/plugin_namestore_sqlite.c
copy to src/identity-provider/plugin_identity_provider_sqlite.c
index 5c3533506..0071528b9 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/identity-provider/plugin_identity_provider_sqlite.c
@@ -19,17 +19,16 @@
   */
 
 /**
- * @file namestore/plugin_namestore_sqlite.c
- * @brief sqlite-based namestore backend
- * @author Christian Grothoff
+ * @file identity-provider/plugin_identity_provider_sqlite.c
+ * @brief sqlite-based idp backend
+ * @author Martin Schanzenbach
  */
 
 #include "platform.h"
-#include "gnunet_namestore_plugin.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_identity_provider_service.h"
+#include "gnunet_identity_provider_plugin.h"
+#include "gnunet_identity_attribute_lib.h"
 #include "gnunet_sq_lib.h"
-#include "namestore.h"
 #include <sqlite3.h>
 
 /**
@@ -50,9 +49,9 @@
  * a failure of the command 'cmd' on file 'filename'
  * with the message given by strerror(errno).
  */
-#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, 
"namestore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, 
__LINE__, sqlite3_errmsg(db->dbh)); } while(0)
+#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, 
"identity-provider", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, 
__LINE__, sqlite3_errmsg(db->dbh)); } while(0)
 
-#define LOG(kind,...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "identity-provider-sqlite", 
__VA_ARGS__)
 
 
 /**
@@ -74,34 +73,29 @@ struct Plugin
   sqlite3 *dbh;
 
   /**
-   * Precompiled SQL to store records.
+   * Precompiled SQL to store ticket.
    */
-  sqlite3_stmt *store_records;
+  sqlite3_stmt *store_ticket;
 
   /**
-   * Precompiled SQL to deltete existing records.
+   * Precompiled SQL to delete existing ticket.
    */
-  sqlite3_stmt *delete_records;
+  sqlite3_stmt *delete_ticket;
 
   /**
-   * Precompiled SQL for iterate records within a zone.
+   * Precompiled SQL to iterate tickets.
    */
-  sqlite3_stmt *iterate_zone;
+  sqlite3_stmt *iterate_tickets;
 
   /**
-   * Precompiled SQL for iterate all records within all zones.
+   * Precompiled SQL to get ticket attributes.
    */
-  sqlite3_stmt *iterate_all_zones;
-
-  /**
-   * Precompiled SQL to for reverse lookup based on PKEY.
-   */
-  sqlite3_stmt *zone_to_name;
-
+  sqlite3_stmt *get_ticket_attrs;
+  
   /**
-   * Precompiled SQL to lookup records based on label.
+   * Precompiled SQL to iterate tickets by audience.
    */
-  sqlite3_stmt *lookup_label;
+  sqlite3_stmt *iterate_tickets_by_audience;
 };
 
 
@@ -135,7 +129,6 @@ sq_prepare (sqlite3 *dbh,
   return result;
 }
 
-
 /**
  * Create our database indices.
  *
@@ -147,15 +140,11 @@ create_indices (sqlite3 * dbh)
   /* create indices */
   if ( (SQLITE_OK !=
        sqlite3_exec (dbh,
-                      "CREATE INDEX IF NOT EXISTS ir_pkey_reverse ON 
ns097records (zone_private_key,pkey)",
-                     NULL, NULL, NULL)) ||
-       (SQLITE_OK !=
-       sqlite3_exec (dbh,
-                      "CREATE INDEX IF NOT EXISTS ir_pkey_iter ON ns097records 
(zone_private_key,rvalue)",
+                      "CREATE INDEX IF NOT EXISTS identity_reverse ON 
identity001tickets (identity,audience)",
                      NULL, NULL, NULL)) ||
        (SQLITE_OK !=
        sqlite3_exec (dbh,
-                      "CREATE INDEX IF NOT EXISTS it_iter ON ns097records 
(rvalue)",
+                      "CREATE INDEX IF NOT EXISTS it_iter ON 
identity001tickets (rnd)",
                      NULL, NULL, NULL)) )
     LOG (GNUNET_ERROR_TYPE_ERROR,
         "Failed to create indices: %s\n",
@@ -163,6 +152,7 @@ create_indices (sqlite3 * dbh)
 }
 
 
+
 #if 0
 #define CHECK(a) GNUNET_break(a)
 #define ENULL NULL
@@ -192,12 +182,12 @@ database_setup (struct Plugin *plugin)
 
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
-                                               "namestore-sqlite",
+                                               "identity-provider-sqlite",
                                                "FILENAME",
                                                &afsdir))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                              "namestore-sqlite",
+                              "identity-provider-sqlite",
                                "FILENAME");
     return GNUNET_SYSERR;
   }
@@ -260,18 +250,16 @@ database_setup (struct Plugin *plugin)
   /* Create table */
   CHECK (SQLITE_OK ==
          sq_prepare (plugin->dbh,
-                     "SELECT 1 FROM sqlite_master WHERE tbl_name = 
'ns097records'",
+                     "SELECT 1 FROM sqlite_master WHERE tbl_name = 
'identity001tickets'",
                      &stmt));
   if ((sqlite3_step (stmt) == SQLITE_DONE) &&
       (sqlite3_exec
        (plugin->dbh,
-        "CREATE TABLE ns097records ("
-        " zone_private_key BLOB NOT NULL DEFAULT '',"
-        " pkey BLOB,"
-       " rvalue INT8 NOT NULL DEFAULT '',"
-       " record_count INT NOT NULL DEFAULT 0,"
-        " record_data BLOB NOT NULL DEFAULT '',"
-        " label TEXT NOT NULL DEFAULT ''"
+        "CREATE TABLE identity001tickets ("
+        " identity BLOB NOT NULL DEFAULT '',"
+        " audience BLOB NOT NULL DEFAULT '',"
+             " rnd INT8 NOT NULL DEFAULT '',"
+        " attributes BLOB NOT NULL DEFAULT ''"
        ")",
        NULL, NULL, NULL) != SQLITE_OK))
   {
@@ -286,35 +274,30 @@ database_setup (struct Plugin *plugin)
 
   if ( (SQLITE_OK !=
         sq_prepare (plugin->dbh,
-                    "INSERT INTO ns097records (zone_private_key, pkey, rvalue, 
record_count, record_data, label)"
-                    " VALUES (?, ?, ?, ?, ?, ?)",
-                    &plugin->store_records)) ||
-       (SQLITE_OK !=
-        sq_prepare (plugin->dbh,
-                    "DELETE FROM ns097records WHERE zone_private_key=? AND 
label=?",
-                    &plugin->delete_records)) ||
+                    "INSERT INTO identity001tickets (identity, audience, rnd, 
attributes)"
+                    " VALUES (?, ?, ?, ?)",
+                    &plugin->store_ticket)) ||
        (SQLITE_OK !=
         sq_prepare (plugin->dbh,
-                    "SELECT record_count,record_data,label"
-                    " FROM ns097records WHERE zone_private_key=? AND pkey=?",
-                    &plugin->zone_to_name)) ||
+                    "DELETE FROM identity001tickets WHERE identity=? AND 
rnd=?",
+                    &plugin->delete_ticket)) ||
        (SQLITE_OK !=
         sq_prepare (plugin->dbh,
-                    "SELECT record_count,record_data,label"
-                    " FROM ns097records WHERE zone_private_key=?"
-                    " ORDER BY rvalue LIMIT 1 OFFSET ?",
-                    &plugin->iterate_zone)) ||
+                    "SELECT identity,audience,rnd,attributes"
+                    " FROM identity001tickets WHERE identity=? AND rnd=?",
+                    &plugin->get_ticket_attrs)) ||
        (SQLITE_OK !=
         sq_prepare (plugin->dbh,
-                    "SELECT record_count,record_data,label,zone_private_key"
-                    " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET ?",
-                    &plugin->iterate_all_zones))  ||
+                    "SELECT identity,audience,rnd,attributes"
+                    " FROM identity001tickets WHERE identity=?"
+                    " ORDER BY rnd LIMIT 1 OFFSET ?",
+                    &plugin->iterate_tickets)) ||
        (SQLITE_OK !=
         sq_prepare (plugin->dbh,
-                    "SELECT record_count,record_data,label,zone_private_key"
-                    " FROM ns097records WHERE zone_private_key=? AND label=?",
-                    &plugin->lookup_label))
-       )
+                    "SELECT identity,audience,rnd,attributes"
+                    " FROM identity001tickets WHERE audience=?"
+                    " ORDER BY rnd LIMIT 1 OFFSET ?",
+                    &plugin->iterate_tickets_by_audience)) ) 
   {
     LOG_SQLITE (plugin,
                 GNUNET_ERROR_TYPE_ERROR,
@@ -336,18 +319,16 @@ database_shutdown (struct Plugin *plugin)
   int result;
   sqlite3_stmt *stmt;
 
-  if (NULL != plugin->store_records)
-    sqlite3_finalize (plugin->store_records);
-  if (NULL != plugin->delete_records)
-    sqlite3_finalize (plugin->delete_records);
-  if (NULL != plugin->iterate_zone)
-    sqlite3_finalize (plugin->iterate_zone);
-  if (NULL != plugin->iterate_all_zones)
-    sqlite3_finalize (plugin->iterate_all_zones);
-  if (NULL != plugin->zone_to_name)
-    sqlite3_finalize (plugin->zone_to_name);
-  if (NULL != plugin->lookup_label)
-    sqlite3_finalize (plugin->lookup_label);
+  if (NULL != plugin->store_ticket)
+    sqlite3_finalize (plugin->store_ticket);
+  if (NULL != plugin->delete_ticket)
+    sqlite3_finalize (plugin->delete_ticket);
+  if (NULL != plugin->iterate_tickets)
+    sqlite3_finalize (plugin->iterate_tickets);
+  if (NULL != plugin->iterate_tickets_by_audience)
+    sqlite3_finalize (plugin->iterate_tickets_by_audience);
+  if (NULL != plugin->get_ticket_attrs)
+    sqlite3_finalize (plugin->get_ticket_attrs);
   result = sqlite3_close (plugin->dbh);
   if (result == SQLITE_BUSY)
   {
@@ -383,135 +364,147 @@ database_shutdown (struct Plugin *plugin)
 
 
 /**
- * Store a record in the datastore.  Removes any existing record in the
- * same zone with the same name.
+ * Store a ticket in the database.
  *
  * @param cls closure (internal context for the plugin)
- * @param zone_key private key of the zone
- * @param label name that is being mapped (at most 255 characters long)
- * @param rd_count number of entries in @a rd array
- * @param rd array of records with data to store
+ * @param ticket the ticket to persist
+ * @param attrs the attributes associated with the ticket
  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
  */
 static int
-namestore_sqlite_store_records (void *cls,
-                               const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*zone_key,
-                               const char *label,
-                               unsigned int rd_count,
-                               const struct GNUNET_GNSRECORD_Data *rd)
+identity_provider_sqlite_store_ticket (void *cls,
+                                       const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                       const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
 {
   struct Plugin *plugin = cls;
+  size_t attrs_len;
+  char *attrs_ser;
   int n;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
-  uint64_t rvalue;
-  size_t data_size;
-  unsigned int i;
-
-  memset (&pkey, 0, sizeof (pkey));
-  for (i=0;i<rd_count;i++)
-    if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type)
-    {
-      GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) ==
-                    rd[i].data_size);
-      GNUNET_memcpy (&pkey,
-                     rd[i].data,
-                     rd[i].data_size);
-      break;
-    }
-  rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                     UINT64_MAX);
-  data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
-                                                 rd);
-  if (data_size > 64 * 65536)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  {
-    /* First delete 'old' records */
-    char data[data_size];
+
+  { 
+    /* First delete duplicates */
     struct GNUNET_SQ_QueryParam dparams[] = {
-      GNUNET_SQ_query_param_auto_from_type (zone_key),
-      GNUNET_SQ_query_param_string (label),
+      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
       GNUNET_SQ_query_param_end
     };
-
-    if (data_size !=
-        GNUNET_GNSRECORD_records_serialize (rd_count,
-                                            rd,
-                                            data_size,
-                                            data))
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
     if (GNUNET_OK !=
-        GNUNET_SQ_bind (plugin->delete_records,
+        GNUNET_SQ_bind (plugin->delete_ticket,
                         dparams))
     {
       LOG_SQLITE (plugin,
-                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                 "sqlite3_bind_XXXX");
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_bind_XXXX");
       GNUNET_SQ_reset (plugin->dbh,
-                       plugin->delete_records);
+                       plugin->delete_ticket);
       return GNUNET_SYSERR;
-
     }
-    n = sqlite3_step (plugin->delete_records);
+    n = sqlite3_step (plugin->delete_ticket);
     GNUNET_SQ_reset (plugin->dbh,
-                     plugin->delete_records);
+                     plugin->delete_ticket);
+    
+    attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs);
+    attrs_ser = GNUNET_malloc (attrs_len);
+    GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs,
+                              attrs_ser);
+    struct GNUNET_SQ_QueryParam sparams[] = {
+      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+      GNUNET_SQ_query_param_auto_from_type (&ticket->audience),
+      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+      GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len),
+      GNUNET_SQ_query_param_end
+    };
 
-    if (0 != rd_count)
+    if (GNUNET_OK !=
+        GNUNET_SQ_bind (plugin->store_ticket,
+                        sparams))
     {
-      uint32_t rd_count32 = (uint32_t) rd_count;
-      struct GNUNET_SQ_QueryParam sparams[] = {
-        GNUNET_SQ_query_param_auto_from_type (zone_key),
-        GNUNET_SQ_query_param_auto_from_type (&rvalue),
-        GNUNET_SQ_query_param_uint64 (&rvalue),
-        GNUNET_SQ_query_param_uint32 (&rd_count32),
-        GNUNET_SQ_query_param_fixed_size (data, data_size),
-        GNUNET_SQ_query_param_string (label),
-        GNUNET_SQ_query_param_end
-      };
-
-      if (GNUNET_OK !=
-          GNUNET_SQ_bind (plugin->store_records,
-                          sparams))
-      {
-       LOG_SQLITE (plugin,
-                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                   "sqlite3_bind_XXXX");
-        GNUNET_SQ_reset (plugin->dbh,
-                         plugin->store_records);
-       return GNUNET_SYSERR;
-      }
-      n = sqlite3_step (plugin->store_records);
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_bind_XXXX");
       GNUNET_SQ_reset (plugin->dbh,
-                       plugin->store_records);
+                       plugin->store_ticket);
+      return GNUNET_SYSERR;
     }
+    n = sqlite3_step (plugin->store_ticket);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->store_ticket);
+    GNUNET_free (attrs_ser);
   }
   switch (n)
   {
-  case SQLITE_DONE:
-    if (0 != rd_count)
+    case SQLITE_DONE:
       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
                        "sqlite",
-                       "Record stored\n");
-    else
+                       "Ticket stored\n");
+      return GNUNET_OK;
+    case SQLITE_BUSY:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_NO;
+    default:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Store a ticket in the database.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param ticket the ticket to delete
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+identity_provider_sqlite_delete_ticket (void *cls,
+                                        const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+{
+  struct Plugin *plugin = cls;
+  int n;
+
+  {  
+    struct GNUNET_SQ_QueryParam sparams[] = {
+      GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+      GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+      GNUNET_SQ_query_param_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_SQ_bind (plugin->delete_ticket,
+                        sparams))
+    {
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_bind_XXXX");
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->store_ticket);
+      return GNUNET_SYSERR;
+    }
+    n = sqlite3_step (plugin->delete_ticket);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->delete_ticket);
+  }
+  switch (n)
+  {
+    case SQLITE_DONE:
       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
                        "sqlite",
-                       "Record deleted\n");
-    return GNUNET_OK;
-  case SQLITE_BUSY:
-    LOG_SQLITE (plugin,
-                GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
-               "sqlite3_step");
-    return GNUNET_NO;
-  default:
-    LOG_SQLITE (plugin,
-                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-               "sqlite3_step");
-    return GNUNET_SYSERR;
+                       "Ticket deleted\n");
+      return GNUNET_OK;
+    case SQLITE_BUSY:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_NO;
+    default:
+      LOG_SQLITE (plugin,
+                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  "sqlite3_step");
+      return GNUNET_SYSERR;
   }
 }
 
@@ -523,85 +516,52 @@ namestore_sqlite_store_records (void *cls,
  *
  * @param plugin plugin context
  * @param stmt to run (and then clean up)
- * @param zone_key private key of the zone
  * @param iter iterator to call with the result
  * @param iter_cls closure for @a iter
  * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, 
#GNUNET_SYSERR on error
  */
 static int
-get_record_and_call_iterator (struct Plugin *plugin,
-                             sqlite3_stmt *stmt,
-                             const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*zone_key,
-                             GNUNET_NAMESTORE_RecordIterator iter,
+get_ticket_and_call_iterator (struct Plugin *plugin,
+                              sqlite3_stmt *stmt,
+                              GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
                               void *iter_cls)
 {
-  uint32_t record_count;
-  size_t data_size;
-  void *data;
-  char *label;
-  struct GNUNET_CRYPTO_EcdsaPrivateKey zk;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
   int ret;
   int sret;
+  size_t attrs_len;
+  char *attrs_ser;
 
   ret = GNUNET_NO;
   if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
   {
     struct GNUNET_SQ_ResultSpec rs[] = {
-      GNUNET_SQ_result_spec_uint32 (&record_count),
-      GNUNET_SQ_result_spec_variable_size (&data, &data_size),
-      GNUNET_SQ_result_spec_string (&label),
+      GNUNET_SQ_result_spec_auto_from_type (&ticket.identity),
+      GNUNET_SQ_result_spec_auto_from_type (&ticket.audience),
+      GNUNET_SQ_result_spec_uint64 (&ticket.rnd),
+      GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser,
+                                           &attrs_len),
       GNUNET_SQ_result_spec_end
-    };
-    struct GNUNET_SQ_ResultSpec rsx[] = {
-      GNUNET_SQ_result_spec_uint32 (&record_count),
-      GNUNET_SQ_result_spec_variable_size (&data, &data_size),
-      GNUNET_SQ_result_spec_string (&label),
-      GNUNET_SQ_result_spec_auto_from_type (&zk),
-      GNUNET_SQ_result_spec_end
-    };
 
-    if (NULL == zone_key)
-    {
-      zone_key = &zk;
-      ret = GNUNET_SQ_extract_result (stmt,
-                                      rsx);
-    }
-    else
-    {
-      ret = GNUNET_SQ_extract_result (stmt,
-                                      rs);
-    }
-    if ( (GNUNET_OK != ret) ||
-         (record_count > 64 * 1024) )
+    };
+    ret = GNUNET_SQ_extract_result (stmt,
+                                    rs);
+    if (GNUNET_OK != ret)
     {
-      /* sanity check, don't stack allocate far too much just
-        because database might contain a large value here */
       GNUNET_break (0);
       ret = GNUNET_SYSERR;
     }
     else
     {
-      struct GNUNET_GNSRECORD_Data rd[record_count];
-
-      if (GNUNET_OK !=
-         GNUNET_GNSRECORD_records_deserialize (data_size,
-                                                data,
-                                               record_count,
-                                                rd))
-      {
-       GNUNET_break (0);
-       ret = GNUNET_SYSERR;
-      }
-      else
-      {
-       if (NULL != iter)
-          iter (iter_cls,
-                zone_key,
-                label,
-                record_count,
-                rd);
-       ret = GNUNET_YES;
-      }
+      attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser,
+                                          attrs_len);
+      if (NULL != iter)
+        iter (iter_cls,
+              &ticket,
+              attrs);
+      GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs);
+      ret = GNUNET_YES;
     }
     GNUNET_SQ_cleanup_result (rs);
   }
@@ -619,44 +579,39 @@ get_record_and_call_iterator (struct Plugin *plugin,
 
 
 /**
- * Lookup records in the datastore for which we are the authority.
+ * Lookup tickets in the datastore.
  *
  * @param cls closure (internal context for the plugin)
- * @param zone private key of the zone
- * @param label name of the record in the zone
+ * @param ticket the ticket to retrieve attributes for
  * @param iter function to call with the result
  * @param iter_cls closure for @a iter
  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
  */
 static int
-namestore_sqlite_lookup_records (void *cls,
-                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*zone,
-                                 const char *label,
-                                 GNUNET_NAMESTORE_RecordIterator iter,
-                                 void *iter_cls)
+identity_provider_sqlite_ticket_get_attrs (void *cls,
+                                           const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                           
GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+                                           void *iter_cls)
 {
   struct Plugin *plugin = cls;
   struct GNUNET_SQ_QueryParam params[] = {
-    GNUNET_SQ_query_param_auto_from_type (zone),
-    GNUNET_SQ_query_param_string (label),
+    GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+    GNUNET_SQ_query_param_uint64 (&ticket->rnd),
     GNUNET_SQ_query_param_end
   };
 
-  if (NULL == zone)
-    return GNUNET_SYSERR;
   if (GNUNET_OK !=
-      GNUNET_SQ_bind (plugin->lookup_label,
+      GNUNET_SQ_bind (plugin->get_ticket_attrs,
                       params))
   {
     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                 "sqlite3_bind_XXXX");
     GNUNET_SQ_reset (plugin->dbh,
-                     plugin->lookup_label);
+                     plugin->get_ticket_attrs);
     return GNUNET_SYSERR;
   }
-  return get_record_and_call_iterator (plugin,
-                                       plugin->lookup_label,
-                                       zone,
+  return get_ticket_and_call_iterator (plugin,
+                                       plugin->get_ticket_attrs,
                                        iter,
                                        iter_cls);
 }
@@ -667,43 +622,44 @@ namestore_sqlite_lookup_records (void *cls,
  * datastore.  Will return at most one result to the iterator.
  *
  * @param cls closure (internal context for the plugin)
- * @param zone hash of public key of the zone, NULL to iterate over all zones
+ * @param identity the issuing identity or audience (depending on audience 
switch)
+ * @param audience GNUNET_YES if identity is audience
  * @param offset offset in the list of all matching records
  * @param iter function to call with the result
  * @param iter_cls closure for @a iter
  * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, 
#GNUNET_SYSERR on error
  */
 static int
-namestore_sqlite_iterate_records (void *cls,
-                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*zone,
-                                 uint64_t offset,
-                                 GNUNET_NAMESTORE_RecordIterator iter,
-                                  void *iter_cls)
+identity_provider_sqlite_iterate_tickets (void *cls,
+                                          const struct 
GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                                          int audience,
+                                          uint64_t offset,
+                                          
GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+                                          void *iter_cls)
 {
   struct Plugin *plugin = cls;
   sqlite3_stmt *stmt;
   int err;
 
-  if (NULL == zone)
+  if (NULL == identity)
   {
-    struct GNUNET_SQ_QueryParam params[] = {
-      GNUNET_SQ_query_param_uint64 (&offset),
-      GNUNET_SQ_query_param_end
-    };
-
-    stmt = plugin->iterate_all_zones;
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  struct GNUNET_SQ_QueryParam params[] = {
+    GNUNET_SQ_query_param_auto_from_type (identity),
+    GNUNET_SQ_query_param_uint64 (&offset),
+    GNUNET_SQ_query_param_end
+  };
+  if (GNUNET_YES == audience)
+  {
+    stmt = plugin->iterate_tickets_by_audience;
     err = GNUNET_SQ_bind (stmt,
                           params);
   }
   else
   {
-    struct GNUNET_SQ_QueryParam params[] = {
-      GNUNET_SQ_query_param_auto_from_type (zone),
-      GNUNET_SQ_query_param_uint64 (&offset),
-      GNUNET_SQ_query_param_end
-    };
-
-    stmt = plugin->iterate_zone;
+    stmt = plugin->iterate_tickets;
     err = GNUNET_SQ_bind (stmt,
                           params);
   }
@@ -711,60 +667,13 @@ namestore_sqlite_iterate_records (void *cls,
   {
     LOG_SQLITE (plugin,
                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-               "sqlite3_bind_XXXX");
+                "sqlite3_bind_XXXX");
     GNUNET_SQ_reset (plugin->dbh,
                      stmt);
     return GNUNET_SYSERR;
   }
-  return get_record_and_call_iterator (plugin,
+  return get_ticket_and_call_iterator (plugin,
                                        stmt,
-                                       zone,
-                                       iter,
-                                       iter_cls);
-}
-
-
-/**
- * Look for an existing PKEY delegation record for a given public key.
- * Returns at most one result to the iterator.
- *
- * @param cls closure (internal context for the plugin)
- * @param zone private key of the zone to look up in, never NULL
- * @param value_zone public key of the target zone (value), never NULL
- * @param iter function to call with the result
- * @param iter_cls closure for @a iter
- * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, 
#GNUNET_SYSERR on error
- */
-static int
-namestore_sqlite_zone_to_name (void *cls,
-                              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                              const struct GNUNET_CRYPTO_EcdsaPublicKey 
*value_zone,
-                              GNUNET_NAMESTORE_RecordIterator iter, void 
*iter_cls)
-{
-  struct Plugin *plugin = cls;
-  struct GNUNET_SQ_QueryParam params[] = {
-    GNUNET_SQ_query_param_auto_from_type (zone),
-    GNUNET_SQ_query_param_auto_from_type (value_zone),
-    GNUNET_SQ_query_param_end
-  };
-
-  if (GNUNET_OK !=
-      GNUNET_SQ_bind (plugin->zone_to_name,
-                      params))
-  {
-    LOG_SQLITE (plugin,
-                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-               "sqlite3_bind_XXXX");
-    GNUNET_SQ_reset (plugin->dbh,
-                     plugin->zone_to_name);
-    return GNUNET_SYSERR;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Performing reverse lookup for `%s'\n",
-       GNUNET_GNSRECORD_z2s (value_zone));
-  return get_record_and_call_iterator (plugin,
-                                       plugin->zone_to_name,
-                                       zone,
                                        iter,
                                        iter_cls);
 }
@@ -773,15 +682,15 @@ namestore_sqlite_zone_to_name (void *cls,
 /**
  * Entry point for the plugin.
  *
- * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
+ * @param cls the "struct GNUNET_IDENTITY_PROVIDER_PluginEnvironment*"
  * @return NULL on error, otherwise the plugin context
  */
 void *
-libgnunet_plugin_namestore_sqlite_init (void *cls)
+libgnunet_plugin_identity_provider_sqlite_init (void *cls)
 {
   static struct Plugin plugin;
   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct GNUNET_NAMESTORE_PluginFunctions *api;
+  struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api;
 
   if (NULL != plugin.cfg)
     return NULL;                /* can only initialize once! */
@@ -792,12 +701,12 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
     database_shutdown (&plugin);
     return NULL;
   }
-  api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
+  api = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_PluginFunctions);
   api->cls = &plugin;
-  api->store_records = &namestore_sqlite_store_records;
-  api->iterate_records = &namestore_sqlite_iterate_records;
-  api->zone_to_name = &namestore_sqlite_zone_to_name;
-  api->lookup_records = &namestore_sqlite_lookup_records;
+  api->store_ticket = &identity_provider_sqlite_store_ticket;
+  api->delete_ticket = &identity_provider_sqlite_delete_ticket;
+  api->iterate_tickets = &identity_provider_sqlite_iterate_tickets;
+  api->get_ticket_attributes = &identity_provider_sqlite_ticket_get_attrs;
   LOG (GNUNET_ERROR_TYPE_INFO,
        _("Sqlite database running\n"));
   return api;
@@ -811,9 +720,9 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
  * @return always NULL
  */
 void *
-libgnunet_plugin_namestore_sqlite_done (void *cls)
+libgnunet_plugin_identity_provider_sqlite_done (void *cls)
 {
-  struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
+  struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
 
   database_shutdown (plugin);
@@ -824,4 +733,4 @@ libgnunet_plugin_namestore_sqlite_done (void *cls)
   return NULL;
 }
 
-/* end of plugin_namestore_sqlite.c */
+/* end of plugin_identity_provider_sqlite.c */
diff --git a/src/identity-provider/plugin_rest_identity_provider.c 
b/src/identity-provider/plugin_rest_identity_provider.c
index 907b28ba9..6eb856435 100644
--- a/src/identity-provider/plugin_rest_identity_provider.c
+++ b/src/identity-provider/plugin_rest_identity_provider.c
@@ -37,6 +37,7 @@
 #include <jansson.h>
 #include <inttypes.h>
 #include "gnunet_signatures.h"
+#include "gnunet_identity_attribute_lib.h"
 #include "gnunet_identity_provider_service.h"
 
 /**
@@ -45,39 +46,40 @@
 #define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp"
 
 /**
- * Issue namespace
+ * Attribute namespace
  */
-#define GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE "/idp/issue"
+#define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes"
 
 /**
- * Check namespace TODO
+ * Ticket namespace
  */
-#define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/idp/check"
+#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets"
 
 /**
- * Token namespace
+ * Revoke namespace
  */
-#define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token"
+#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke"
 
 /**
- * The parameter name in which the ticket must be provided
+ * Revoke namespace
  */
-#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket"
+#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume"
 
 /**
- * The parameter name in which the expected nonce must be provided
+ * Attribute key
  */
-#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce"
+#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute"
 
 /**
- * The parameter name in which the ticket must be provided
+ * Ticket key
  */
-#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token"
+#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
+
 
 /**
- * The URL parameter name in which the nonce must be provided
+ * Value key
  */
-#define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce"
+#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value"
 
 /**
  * State while collecting all egos
@@ -89,41 +91,6 @@
  */
 #define ID_REST_STATE_POST_INIT 1
 
-/**
- * Resource type
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_TOKEN "token"
-
-/**
- * URL parameter to create a GNUid token for a specific audience
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST "audience"
-
-/**
- * URL parameter to create a GNUid token for a specific issuer (EGO)
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST "issuer"
-
-/**
- * Attributes passed to issue request
- */
-#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
-
-/**
- * Token expiration string
- */
-#define GNUNET_IDENTITY_TOKEN_EXP_STRING "expiration"
-
-/**
- * Error messages
- */
-#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
-#define GNUNET_REST_ERROR_NO_DATA "No data"
-
-/**
- * GNUid token lifetime
- */
-#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
 
 /**
  * The configuration handle
@@ -198,11 +165,6 @@ struct RequestHandle
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
 
   /**
-   * Handle to the rest connection
-   */
-  struct GNUNET_REST_RequestHandle *conndata_handle;
-
-  /**
    * The processing state
    */
   int state;
@@ -213,6 +175,12 @@ struct RequestHandle
   struct GNUNET_IDENTITY_Handle *identity_handle;
 
   /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+
+  /**
    * IDENTITY Operation
    */
   struct GNUNET_IDENTITY_Operation *op;
@@ -228,19 +196,14 @@ struct RequestHandle
   struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
 
   /**
-   * Handle to NS service
-   */
-  struct GNUNET_NAMESTORE_Handle *ns_handle;
-
-  /**
-   * NS iterator
+   * Attribute iterator
    */
-  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it;
 
   /**
-   * NS Handle
+   * Ticket iterator
    */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+  struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it;
 
   /**
    * Desired timeout for the lookup (default is no timeout).
@@ -285,6 +248,7 @@ struct RequestHandle
 };
 
 
+
 /**
  * Cleanup lookup handle
  * @param handle Handle to clean up
@@ -302,14 +266,12 @@ cleanup_handle (struct RequestHandle *handle)
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
   if (NULL != handle->identity_handle)
     GNUNET_IDENTITY_disconnect (handle->identity_handle);
+  if (NULL != handle->attr_it)
+    GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it);
+  if (NULL != handle->ticket_it)
+    GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it);
   if (NULL != handle->idp)
     GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp);
-  if (NULL != handle->ns_it)
-    GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
-  if (NULL != handle->ns_qe)
-    GNUNET_NAMESTORE_cancel (handle->ns_qe);
-  if (NULL != handle->ns_handle)
-    GNUNET_NAMESTORE_disconnect (handle->ns_handle);
   if (NULL != handle->url)
     GNUNET_free (handle->url);
   if (NULL != handle->emsg)
@@ -326,6 +288,12 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_free (handle);
 }
 
+static void
+cleanup_handle_delayed (void *cls)
+{
+  cleanup_handle (cls);
+}
+
 
 /**
  * Task run on error, sends error message.  Cleans up everything.
@@ -363,622 +331,663 @@ do_timeout (void *cls)
 }
 
 
-/**
- * Task run on shutdown.  Cleans up everything.
- *
- * @param cls unused
- */
 static void
-do_cleanup_handle_delayed (void *cls)
+collect_error_cb (void *cls)
 {
   struct RequestHandle *handle = cls;
 
-  cleanup_handle (handle);
+  do_error (handle);
 }
 
-
-/**
- * Get a ticket for identity
- * @param cls the handle
- * @param ticket the ticket returned from the idp
- */
 static void
-token_creat_cont (void *cls,
-                  const char *label,
-                  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-                  const struct GNUNET_IDENTITY_PROVIDER_Token *token)
+finished_cont (void *cls,
+               int32_t success,
+               const char *emsg)
 {
-  struct GNUNET_JSONAPI_Resource *json_resource;
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
-  json_t *ticket_json;
-  json_t *token_json;
-  char *ticket_str;
-  char *token_str;
-  char *result_str;
 
-  if (NULL == ticket)
+  resp = GNUNET_REST_create_response (emsg);
+  if (GNUNET_OK != success)
   {
-    handle->emsg = GNUNET_strdup ("Error in token issue");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
 
-  handle->resp_object = GNUNET_JSONAPI_document_new ();
-  json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
-                                                    label);
-  ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
-  token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
-  ticket_json = json_string (ticket_str);
-  token_json = json_string (token_str);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                         
GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
-                                         ticket_json);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                         
GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN,
-                                         token_json);
-  GNUNET_free (ticket_str);
-  GNUNET_free (token_str);
-  json_decref (ticket_json);
-  json_decref (token_json);
-  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+/**
+ * Return attributes for identity
+ *
+ * @param cls the request handle
+ */
+static void
+return_response (void *cls)
+{
+  char* result_str;
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
 
   GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
   resp = GNUNET_REST_create_response (result_str);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
-  GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
+}
+
+
+static void
+collect_finished_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  //Done
+  handle->attr_it = NULL;
+  handle->ticket_it = NULL;
+  GNUNET_SCHEDULER_add_now (&return_response, handle);
 }
 
 
 /**
- * Continueationf for token issue request
+ * Collect all attributes for an ego
  *
- * @param con the Rest handle
- * @param url the requested url
- * @param cls the request handle
  */
 static void
-issue_token_cont (struct GNUNET_REST_RequestHandle *con,
-                  const char *url,
-                  void *cls)
+ticket_collect (void *cls,
+                const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
 {
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  const char *egoname;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  struct RequestHandle *handle = cls;
+  json_t *value;
+  char* tmp;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                             sizeof (uint64_t));
+  json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_IDENTITY_TICKET,
+                                                       tmp);
+  GNUNET_free (tmp);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
+                                             sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "issuer",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
+                                             sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "audience",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                             sizeof (uint64_t));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "rnd",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it);
+}
+
 
+
+/**
+ * List tickets for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                   const char* url,
+                   void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
-  struct GNUNET_HashCode key;
-  struct MHD_Response *resp;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
-  struct GNUNET_TIME_Relative etime_rel;
-  struct GNUNET_TIME_Absolute exp_time;
-  char *ego_val;
-  char *audience;
-  char *exp_str;
-  char *nonce_str;
-  char *scopes;
-  uint64_t time;
-  uint64_t nonce;
-
-  if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url,
-                                                
GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
-    cleanup_handle (handle);
-    return;
-  }
-  egoname = NULL;
-  ego_entry = NULL;
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
-                      &key);
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                               &key) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Issuer not found\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  ego_val = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                               &key);
-  if (NULL == ego_val)
+  char *identity;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
+       strlen (handle->url))
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Ego invalid: %s\n",
-               ego_val);
     return;
   }
+  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
+
   for (ego_entry = handle->ego_head;
        NULL != ego_entry;
        ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+
+  if (NULL == ego_entry)
   {
-    if (0 != strcmp (ego_val, ego_entry->identifier))
-      continue;
-    egoname = ego_entry->identifier;
-    break;
-  }
-  if ( (NULL == egoname) ||
-       (NULL == ego_entry) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Ego not found: %s\n",
-               ego_val);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+                identity);
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
     return;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Ego to issue token for: %s\n",
-             egoname);
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
+  handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start 
(handle->idp,
+                                                                       
priv_key,
+                                                                       
&collect_error_cb,
+                                                                       handle,
+                                                                       
&ticket_collect,
+                                                                       handle,
+                                                                       
&collect_finished_cb,
+                                                                       handle);
+}
 
 
-  //Meta info
-  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_ATTR_LIST,
-                      strlen (GNUNET_IDENTITY_TOKEN_ATTR_LIST),
-                      &key);
+static void
+add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity;
+  const char* name_str;
+  const char* value_str;
 
-  scopes = NULL;
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                               &key) )
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *value_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
+       strlen (handle->url))
   {
-    handle->emsg = GNUNET_strdup ("Scopes missing!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  scopes = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                              &key);
-
-
-  //Token audience
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST),
-                      &key);
-  audience = NULL;
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                               &key) )
+  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+
+  if (NULL == ego_entry)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Audience missing!\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
+                "Identity unknown (%s)\n", identity);
+    GNUNET_JSONAPI_document_delete (json_obj);
     return;
   }
-  audience = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                                &key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Audience to issue token for: %s\n",
-             audience);
-
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                      &pub_key);
-  GNUNET_STRINGS_string_to_data (audience,
-                                 strlen (audience),
-                                 &aud_key,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
 
-  //Remote nonce
-  nonce_str = NULL;
-  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
-                      strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
-                      &key);
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                               &key) )
+  if (0 >= handle->rest_handle->data_size)
   {
-    handle->emsg = GNUNET_strdup ("Request nonce missing!\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  nonce_str = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                                 &key);
-  GNUNET_assert (NULL != nonce_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Request nonce: %s\n",
-             nonce_str);
-  GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce));
-
-  //Get expiration for token from URL parameter
-  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
-                      strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING),
-                      &key);
-
-  exp_str = NULL;
-  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                                            &key))
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
   {
-    exp_str = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                                 &key);
-  }
-  if (NULL == exp_str) {
-    handle->emsg = GNUNET_strdup ("No expiration given!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_fancy_time_to_relative (exp_str,
-                                             &etime_rel))
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
   {
-    handle->emsg = GNUNET_strdup ("Expiration invalid!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  time = GNUNET_TIME_absolute_get().abs_value_us;
-  exp_time.abs_value_us = time + etime_rel.rel_value_us;
-
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       
GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  name_str = GNUNET_JSONAPI_resource_get_id (json_res);
+  value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                  "value");
+  value_str = json_string_value (value_json);
+  attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str,
+                                                      
GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
+                                                      value_str,
+                                                      strlen (value_str) + 1);
   handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->idp_op = GNUNET_IDENTITY_PROVIDER_issue_token (handle->idp,
-                                                         priv_key,
-                                                         &aud_key,
-                                                         scopes,
-                                                         exp_time,
-                                                         nonce,
-                                                         &token_creat_cont,
-                                                         handle);
-
-}
-
-
-/**
- * Build a GNUid token for identity
- *
- * @param cls the request handle
- */
-static void
-return_token_list (void *cls)
-{
-  char* result_str;
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  cleanup_handle (handle);
+  handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp,
+                                                             identity_priv,
+                                                             attribute,
+                                                             &finished_cont,
+                                                             handle);
+  GNUNET_free (attribute);
+  GNUNET_JSONAPI_document_delete (json_obj);
 }
 
 
-static void
-token_collect_error_cb (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  do_error (handle);
-}
-
 
 /**
- * Collect all tokens for an ego
- *
- * TODO move this into the identity-provider service
+ * Collect all attributes for an ego
  *
  */
 static void
-token_collect (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *label,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd);
-
-
-static void
-token_collect_finished_cb (void *cls)
+attr_collect (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+              const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
 {
+  struct GNUNET_JSONAPI_Resource *json_resource;
   struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_tmp;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-
-  ego_tmp = handle->ego_head;
-  GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                               handle->ego_tail,
-                               ego_tmp);
-  GNUNET_free (ego_tmp->identifier);
-  GNUNET_free (ego_tmp->keystring);
-  GNUNET_free (ego_tmp);
-
-  if (NULL == handle->ego_head)
+  json_t *value;
+  
+  if ((NULL == attr->name) || (NULL == attr->data))
   {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
-    handle->ns_it = NULL;
-    GNUNET_SCHEDULER_add_now (&return_token_list, handle);
+    GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
     return;
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Next ego: %s\n",
-              handle->ego_head->identifier);
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                         priv_key,
-                                                         
&token_collect_error_cb,
-                                                         handle,
-                                                         &token_collect,
-                                                         handle,
-                                                         
&token_collect_finished_cb,
-                                                         handle);
-}
-
-
-/**
- * Collect all tokens for an ego
- *
- * TODO move this into the identity-provider service
- *
- */
-static void
-token_collect (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *label,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  int i;
-  char* data;
-  struct GNUNET_JSONAPI_Resource *json_resource;
-  json_t *issuer;
-  json_t *token;
-
-  for (i = 0; i < rd_count; i++)
-  {
-    if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
-    {
-      data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
-                                               rd[i].data,
-                                               rd[i].data_size);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
-      json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                                        label);
-      issuer = json_string (handle->ego_head->identifier);
-      GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                             
GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                                             issuer);
-      json_decref (issuer);
-      token = json_string (data);
-      GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                             
GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                             token);
-      json_decref (token);
-
-      GNUNET_JSONAPI_document_resource_add (handle->resp_object, 
json_resource);
-      GNUNET_free (data);
-    }
-  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+              attr->name);
+  json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
+                                               attr->name);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
 
-  GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
+  value = json_string (attr->data);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "value",
+                                    value);
+  json_decref (value);
+  GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it);
 }
 
 
 
 /**
- * Respond to OPTIONS request
+ * List attributes for identity request
  *
  * @param con_handle the connection handle
  * @param url the url
  * @param cls the RequestHandle
  */
 static void
-list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                 const char* url,
-                 void *cls)
+list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                     const char* url,
+                     void *cls)
 {
-  char* ego_val;
-  struct GNUNET_HashCode key;
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
+  char *identity;
 
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
-                      &key);
-
-  if ( GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                               &key) )
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >=
+       strlen (handle->url))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No issuer given.\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  ego_val = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                               &key);
-  GNUNET_assert (NULL != ego_val);
-  //Remove non-matching egos
+  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1;
+
   for (ego_entry = handle->ego_head;
-       NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    if (0 != strcmp (ego_val, ego_tmp->identifier))
-    {
-      GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                   handle->ego_tail,
-                                   ego_tmp);
-      GNUNET_free (ego_tmp->identifier);
-      GNUNET_free (ego_tmp->keystring);
-      GNUNET_free (ego_tmp);
-    }
-  }
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
   handle->resp_object = GNUNET_JSONAPI_document_new ();
-  if (NULL == handle->ego_head)
+
+
+  if (NULL == ego_entry)
   {
     //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No results.\n");
-    GNUNET_SCHEDULER_add_now (&return_token_list, handle);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+                identity);
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
     return;
   }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                         priv_key,
-                                                         
&token_collect_error_cb,
-                                                         handle,
-                                                         &token_collect,
-                                                         handle,
-                                                         
&token_collect_finished_cb,
-                                                         handle);
-
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
+  handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp,
+                                                                   priv_key,
+                                                                   
&collect_error_cb,
+                                                                   handle,
+                                                                   
&attr_collect,
+                                                                   handle,
+                                                                   
&collect_finished_cb,
+                                                                   handle);
 }
 
-/**
- * Return token to requestor
- *
- * @param cls request handle
- * @param token the token
- */
+
 static void
-exchange_cont (void *cls,
-               const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-               uint64_t ticket_nonce)
+revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
 {
-  json_t *root;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity_str;
+  const char* audience_str;
+  const char* rnd_str;
+
   struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
   struct MHD_Response *resp;
-  struct GNUNET_HashCode key;
-  char* result;
-  char* token_str;
-  char* nonce_str;
-  uint64_t expected_nonce;
-
-  //Get nonce
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE,
-                      strlen 
(GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE),
-                      &key);
-
-  if ( GNUNET_NO ==
-       GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                               &key) )
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *rnd_json;
+  json_t *identity_json;
+  json_t *audience_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
   {
-    handle->emsg = GNUNET_strdup ("No nonce given.");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  nonce_str = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                                  &key);
-  GNUNET_assert (NULL != nonce_str);
-  GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
 
-  if (ticket_nonce != expected_nonce)
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Ticket nonce %"SCNu64" does not match expected nonce 
%"SCNu64"\n",
-                ticket_nonce, expected_nonce);
-    handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected 
nonce\n");
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       
GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "rnd");
+  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "identity");
+  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "audience");
+  rnd_str = json_string_value (rnd_json);
+  identity_str = json_string_value (identity_json);
+  audience_str = json_string_value (audience_json);
+
+  GNUNET_STRINGS_string_to_data (rnd_str,
+                                 strlen (rnd_str),
+                                 &ticket.rnd,
+                                 sizeof (uint64_t));
+  GNUNET_STRINGS_string_to_data (identity_str,
+                                 strlen (identity_str),
+                                 &ticket.identity,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  GNUNET_STRINGS_string_to_data (audience_str,
+                                 strlen (audience_str),
+                                 &ticket.audience,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
 
-  root = json_object ();
-  token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
-  json_object_set_new (root, "token", json_string (token_str));
-  json_object_set_new (root, "token_type", json_string ("jwt"));
-  GNUNET_free (token_str);
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                        &tmp_pk);
+    if (0 == memcmp (&ticket.identity,
+                     &tmp_pk,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      break;
+  }
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity_str);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
 
-  result = json_dumps (root, JSON_INDENT(1));
-  resp = GNUNET_REST_create_response (result);
-  GNUNET_free (result);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  cleanup_handle (handle);
-  json_decref (root);
+  handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
+  handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp,
+                                                           identity_priv,
+                                                           &ticket,
+                                                           &finished_cont,
+                                                           handle);
+  GNUNET_JSONAPI_document_delete (json_obj);
 }
 
-
-/**
- *
- * Callback called when identity for token exchange has been found
- *
- * @param cls request handle
- * @param ego the identity to use as issuer
- * @param ctx user context
- * @param name identity name
- *
- */
 static void
-exchange_token_ticket_cb (void *cls,
-                          struct GNUNET_IDENTITY_Ego *ego,
-                          void **ctx,
-                          const char *name)
+consume_cont (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+              const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
 {
   struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode key;
-  struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
-  char* ticket_str;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *value;
 
-  handle->op = NULL;
+  if (NULL == identity)
+  {
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+              attr->name);
+  json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
+                                               attr->name);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  value = json_string (attr->data);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "value",
+                                    value);
+  json_decref (value);
+}
 
-  if (NULL == ego)
+static void
+consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                     const char* url,
+                     void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity_str;
+  const char* audience_str;
+  const char* rnd_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *rnd_json;
+  json_t *identity_json;
+  json_t *audience_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
   {
-    handle->emsg = GNUNET_strdup ("No identity found.");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
 
-  //Get ticket
-  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
-                      strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET),
-                      &key);
-
-  if ( GNUNET_NO ==
-       GNUNET_CONTAINER_multihashmap_contains 
(handle->conndata_handle->url_param_map,
-                                               &key) )
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
   {
-    handle->emsg = GNUNET_strdup ("No ticket given.");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  ticket_str = GNUNET_CONTAINER_multihashmap_get 
(handle->conndata_handle->url_param_map,
-                                                  &key);
-  handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
-  GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str,
-                                             &ticket);
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       
GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "rnd");
+  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "identity");
+  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "audience");
+  rnd_str = json_string_value (rnd_json);
+  identity_str = json_string_value (identity_json);
+  audience_str = json_string_value (audience_json);
+
+  GNUNET_STRINGS_string_to_data (rnd_str,
+                                 strlen (rnd_str),
+                                 &ticket.rnd,
+                                 sizeof (uint64_t));
+  GNUNET_STRINGS_string_to_data (identity_str,
+                                 strlen (identity_str),
+                                 &ticket.identity,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  GNUNET_STRINGS_string_to_data (audience_str,
+                                 strlen (audience_str),
+                                 &ticket.audience,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
 
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                        &tmp_pk);
+    if (0 == memcmp (&ticket.audience,
+                     &tmp_pk,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      break;
+  }
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity_str);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
   handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
-  handle->idp_op = GNUNET_IDENTITY_PROVIDER_exchange_ticket (handle->idp,
-                                                             ticket,
-                                                             handle->priv_key,
-                                                             &exchange_cont,
-                                                             handle);
-  GNUNET_IDENTITY_PROVIDER_ticket_destroy (ticket);
-
+  handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp,
+                                                            identity_priv,
+                                                            &ticket,
+                                                            &consume_cont,
+                                                            handle);
+  GNUNET_JSONAPI_document_delete (json_obj);
 }
 
 
 
 /**
- * Respond to issue request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                            const char* url,
-                            void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  //Get token from GNS
-  handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
-                                    "gns-master",
-                                    &exchange_token_ticket_cb,
-                                    handle);
-}
-
-/**
  * Respond to OPTIONS request
  *
  * @param con_handle the connection handle
@@ -1013,15 +1022,17 @@ init_cont (struct RequestHandle *handle)
 {
   struct GNUNET_REST_RequestHandlerError err;
   static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, 
&issue_token_cont},
-    //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, 
&check_token_cont},
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, 
&list_token_cont},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, 
&options_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, 
&exchange_token_ticket_cont},
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, 
&list_attribute_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, 
&add_attribute_cont},
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, 
&list_tickets_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, 
&revoke_ticket_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, 
&consume_ticket_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
+      &options_cont},
     GNUNET_REST_HANDLER_END
   };
 
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle,
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
                                                handlers,
                                                &err,
                                                handle))
@@ -1092,19 +1103,8 @@ list_ego (void *cls,
 
 }
 
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for callback function
- * @return GNUNET_OK if request accepted
- */
 static void
-rest_identity_process_request(struct GNUNET_REST_RequestHandle 
*conndata_handle,
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
                               GNUNET_REST_ResultProcessor proc,
                               void *proc_cls)
 {
@@ -1114,10 +1114,9 @@ rest_identity_process_request(struct 
GNUNET_REST_RequestHandle *conndata_handle,
   handle->proc_cls = proc_cls;
   handle->proc = proc;
   handle->state = ID_REST_STATE_INIT;
-  handle->conndata_handle = conndata_handle;
+  handle->rest_handle = rest_handle;
 
-
-  handle->url = GNUNET_strdup (conndata_handle->url);
+  handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url)-1] == '/')
     handle->url[strlen (handle->url)-1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1162,8 +1161,8 @@ libgnunet_plugin_rest_identity_provider_init (void *cls)
                    MHD_HTTP_METHOD_DELETE,
                    MHD_HTTP_METHOD_OPTIONS);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              _("Identity Token REST API initialized\n"));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Identity Provider REST API initialized\n"));
   return api;
 }
 
@@ -1184,8 +1183,8 @@ libgnunet_plugin_rest_identity_provider_done (void *cls)
   GNUNET_free_non_null (allow_methods);
   GNUNET_free (api);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Identity Token REST plugin is finished\n");
+              "Identity Provider REST plugin is finished\n");
   return NULL;
 }
 
-/* end of plugin_rest_gns.c */
+/* end of plugin_rest_identity_provider.c */
diff --git a/src/gns/test_gns_lookup.conf b/src/identity-provider/test_idp.conf
similarity index 51%
copy from src/gns/test_gns_lookup.conf
copy to src/identity-provider/test_idp.conf
index ea8c7c3fc..2b76c7bf2 100644
--- a/src/gns/test_gns_lookup.conf
+++ b/src/identity-provider/test_idp.conf
@@ -1,14 +1,22 @@
address@hidden@ test_gns_defaults.conf
address@hidden@ test_idp_defaults.conf
 
 [PATHS]
-GNUNET_TEST_HOME = /tmp/test-gnunet-gns-peer-1/
+GNUNET_TEST_HOME = /tmp/test-gnunet-idp-peer-1/
 
 [dht]
 AUTOSTART = YES
 
+[rest]
+AUTOSTART = YES
+#PREFIX = valgrind --leak-check=full --track-origins=yes 
--log-file=/tmp/restlog
+
 [transport]
 PLUGINS =
 
+[identity-provider]
+AUTOSTART = YES
+#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes 
--log-file=/tmp/idplog
+
 [gns]
 #PREFIX = valgrind --leak-check=full --track-origins=yes
 AUTOSTART = YES
@@ -18,6 +26,3 @@ DEFAULT_LOOKUP_TIMEOUT = 15 s
 RECORD_PUT_INTERVAL = 1 h
 ZONE_PUBLISH_TIME_WINDOW = 1 h
 DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
-
-[revocation]
-WORKBITS = 1
diff --git a/src/identity-provider/test_idp.sh 
b/src/identity-provider/test_idp.sh
new file mode 100755
index 000000000..598d1008c
--- /dev/null
+++ b/src/identity-provider/test_idp.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+#trap "gnunet-arm -e -c test_idp_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+valgrind gnunet-idp -e testego -a email -V address@hidden -c test_idp.conf
+gnunet-idp -e testego -a name -V John -c test_idp.conf
+gnunet-idp -e testego -D -c test_idp.conf
+gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_attribute.sh 
b/src/identity-provider/test_idp_attribute.sh
new file mode 100755
index 000000000..7f0f06dac
--- /dev/null
+++ b/src/identity-provider/test_idp_attribute.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+#gnunet-arm -i rest -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+gnunet-identity -C rpego -c test_idp.conf
+TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print 
$3}')
+gnunet-idp -e testego -a email -V address@hidden -c test_idp.conf
+gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
+if test $? != 0
+then
+  echo "Failed."
+  exit 1
+fi
+
+#curl localhost:7776/idp/attributes/testego
+gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_consume.sh 
b/src/identity-provider/test_idp_consume.sh
new file mode 100755
index 000000000..11f6865a4
--- /dev/null
+++ b/src/identity-provider/test_idp_consume.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+#gnunet-arm -i rest -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+gnunet-identity -C rpego -c test_idp.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print 
$3}')
+TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print 
$3}')
+gnunet-idp -e testego -a email -V address@hidden -c test_idp.conf
+gnunet-idp -e testego -a name -V John -c test_idp.conf
+TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c 
test_idp.conf | awk '{print $1}')
+gnunet-idp -e rpego -C $TICKET -c test_idp.conf > /dev/null 2>&1
+
+if test $? != 0
+then
+  "Failed."
+  exit 1
+fi
+#curl http://localhost:7776/idp/tickets/testego
+gnunet-arm -e -c test_idp.conf
diff --git a/src/gns/test_gns_defaults.conf 
b/src/identity-provider/test_idp_defaults.conf
similarity index 88%
copy from src/gns/test_gns_defaults.conf
copy to src/identity-provider/test_idp_defaults.conf
index 27e9c2c31..10d89c2fb 100644
--- a/src/gns/test_gns_defaults.conf
+++ b/src/identity-provider/test_idp_defaults.conf
@@ -1,7 +1,7 @@
 @INLINE@ ../../contrib/no_forcestart.conf
 
 [PATHS]
-GNUNET_TEST_HOME = /tmp/test-gnunet-gns-testing/
+GNUNET_TEST_HOME = /tmp/test-gnunet-idp-testing/
 
 [namestore-sqlite]
 FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
diff --git a/src/identity-provider/test_idp_issue.sh 
b/src/identity-provider/test_idp_issue.sh
new file mode 100755
index 000000000..90487ee73
--- /dev/null
+++ b/src/identity-provider/test_idp_issue.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+#gnunet-arm -i rest -c test_idp.conf
+gnunet-identity -C testego -c test_idp.conf
+gnunet-identity -C rpego -c test_idp.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print 
$3}')
+TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print 
$3}')
+gnunet-idp -e testego -a email -V address@hidden -c test_idp.conf > /dev/null 
2>&1
+gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
+#gnunet-idp -e testego -D -c test_idp.conf
+gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf > 
/dev/null 2>&1
+if test $? != 0
+then
+  echo "Failed."
+  exit 1
+fi
+#curl http://localhost:7776/idp/attributes/testego
+gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp_revoke.sh 
b/src/identity-provider/test_idp_revoke.sh
new file mode 100755
index 000000000..d5c2c3f77
--- /dev/null
+++ b/src/identity-provider/test_idp_revoke.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_idp.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_idp.conf
+gnunet-identity -C alice -c test_idp.conf
+gnunet-identity -C bob -c test_idp.conf
+gnunet-identity -C eve -c test_idp.conf
+ALICE_KEY=$(gnunet-identity -d -c test_idp.conf | grep alice | awk '{print 
$3}')
+BOB_KEY=$(gnunet-identity -d -c test_idp.conf | grep bob | awk '{print $3}')
+EVE_KEY=$(gnunet-identity -d -c test_idp.conf | grep eve | awk '{print $3}')
+
+gnunet-idp -e alice -a email -V address@hidden -c test_idp.conf 
+gnunet-idp -e alice -a name -V John -c test_idp.conf
+TICKET_BOB=$(gnunet-idp -e alice -i "email,name" -r $BOB_KEY -c test_idp.conf 
| awk '{print $1}')
+#gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf
+TICKET_EVE=$(gnunet-idp -e alice -i "email" -r $EVE_KEY -c test_idp.conf | awk 
'{print $1}')
+
+
+#echo "Consuming $TICKET"
+#gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf
+gnunet-idp -e alice -R $TICKET_EVE -c test_idp.conf
+
+gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf  > /dev/null 2>&1
+if test $? == 0
+then 
+  echo "Eve can still resolve attributes..."
+  gnunet-arm -e -c test_idp.conf
+  exit 1
+fi
+gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf > /dev/null 2>&1
+if test $? != 0
+then
+  echo "Bob cannot resolve attributes..."
+  gnunet-arm -e -c test_idp.conf
+  exit 1
+fi
+
+gnunet-arm -e -c test_idp.conf
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 94e8c5e94..b8e70fffb 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -42,8 +42,7 @@ libexec_PROGRAMS = \
 if HAVE_MHD
 if HAVE_JSON
 plugin_LTLIBRARIES = \
-  libgnunet_plugin_rest_identity.la \
-  libgnunet_plugin_gnsrecord_identity.la
+  libgnunet_plugin_rest_identity.la 
 endif
 endif
 
@@ -55,14 +54,6 @@ gnunet_service_identity_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL)
 
-libgnunet_plugin_gnsrecord_identity_la_SOURCES = \
-  plugin_gnsrecord_identity.c
-libgnunet_plugin_gnsrecord_identity_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(LTLIBINTL)
-libgnunet_plugin_gnsrecord_identity_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
 
 libgnunet_plugin_rest_identity_la_SOURCES = \
   plugin_rest_identity.c
diff --git a/src/identity/plugin_rest_identity.c 
b/src/identity/plugin_rest_identity.c
index e64b2685a..5f34d0f1b 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -427,9 +427,6 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con,
       continue;
     json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_IDENTITY_EGO,
                                                       ego_entry->keystring);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Egoname: %s\n",
-                ego_entry->identifier);
     name_str = json_string (ego_entry->identifier);
     GNUNET_JSONAPI_resource_add_attr (
                                            json_resource,
diff --git a/src/include/gnunet_abe_lib.h b/src/include/gnunet_abe_lib.h
new file mode 100644
index 000000000..f73ea2431
--- /dev/null
+++ b/src/include/gnunet_abe_lib.h
@@ -0,0 +1,193 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2018 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file include/gnunet_abe_lib.h
+ * @brief Attribute-Based Encryption primitives for GNUnet
+ *
+ * @author Martin Schanzenbach
+ *
+ * @defgroup abe  ABE Crypto library: Attribute-Based Encryption operations
+ *
+ */
+#ifndef GNUNET_ABE_LIB_H
+#define GNUNET_ABE_LIB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_common.h"
+#include <gcrypt.h>
+
+/**
+ * @brief type for ABE master keys
+ */
+struct GNUNET_CRYPTO_AbeMasterKey;
+
+/**
+ * @brief type for ABE keys
+ */
+struct GNUNET_CRYPTO_AbeKey;
+
+
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE master key. Caller must free return value.
+ *
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
+ */
+struct GNUNET_ABE_AbeMasterKey *
+GNUNET_ABE_cpabe_create_master_key (void);
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE master key.
+ *
+ * @param key the master key
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key);
+
+/**
+ * @ingroup abe
+ * Create a new CP-ABE key. Caller must free return value.
+ *
+ * @param key the master key
+ * @param attrs the attributes to append to the key
+ * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
+ */
+struct GNUNET_ABE_AbeKey *
+GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
+                                char **attrs);
+
+/**
+ * @ingroup abe
+ * Delete a CP-ABE key.
+ *
+ * @param key the key to delete
+ * @param delete_pub GNUNE_YES if the public key should also be freed (bug in 
gabe)
+ * @return fresh private key; free using #GNUNET_free
+ */
+void
+GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
+                                int delete_pub);
+
+
+/**
+ * @ingroup abe
+ * Encrypt a block using  sessionkey.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param policy the ABE policy
+ * @param key the key used to encrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_encrypt (const void *block,
+                             size_t size,
+                             const char *policy,
+                             const struct GNUNET_ABE_AbeMasterKey *key,
+                             void **result);
+
+/**
+ * @ingroup abe
+ * Decrypt a block using the ABE key.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param key the key used to decrypt
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_decrypt (const void *block,
+                             size_t size,
+                             const struct GNUNET_ABE_AbeKey *key,
+                             void **result);
+
+/**
+ * @ingroup abe
+ * Serialize an ABE key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
+                                   void **result);
+
+/**
+ * @ingroup abe
+ * Deserialize a serialized ABE key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeKey*
+GNUNET_ABE_cpabe_deserialize_key (const void *data,
+                                     size_t len);
+
+/**
+ * @ingroup abe
+ * Serialize an ABE master key.
+ *
+ * @param key the key to serialize
+ * @param result the result buffer. Will be allocated. Free using #GNUNET_free
+ * @return the size of the encrypted block, -1 for errors
+ */
+ssize_t
+GNUNET_ABE_cpabe_serialize_master_key (const struct GNUNET_ABE_AbeMasterKey 
*key,
+                                          void **result);
+
+/**
+ * @ingroup abe
+ * Deserialize an ABE master key.
+ *
+ * @param data the data to deserialize
+ * @param len the length of the data.
+ * @return the ABE key. NULL of unsuccessful
+ */
+struct GNUNET_ABE_AbeMasterKey*
+GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
+                                            size_t len);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef GNUNET_ABE_LIB_H */
+#endif
+/* end of gnunet_abe_lib.h */
diff --git a/src/include/gnunet_credential_service.h 
b/src/include/gnunet_credential_service.h
index 9e765c12b..7d6f9e973 100644
--- a/src/include/gnunet_credential_service.h
+++ b/src/include/gnunet_credential_service.h
@@ -34,6 +34,7 @@
 
 #include "gnunet_util_lib.h"
 #include "gnunet_gns_service.h"
+#include "gnunet_identity_service.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -52,7 +53,157 @@ struct GNUNET_CREDENTIAL_Handle;
 /**
  * Handle to control a lookup operation.
  */
-struct GNUNET_CREDENTIAL_LookupRequest;
+struct GNUNET_CREDENTIAL_Request;
+
+/*
+* Enum used for checking whether the issuer has the authority to issue 
credentials or is just a subject
+*/
+enum GNUNET_CREDENTIAL_CredentialFlags {
+
+  //Subject had credentials before, but have been revoked now
+  GNUNET_CREDENTIAL_FLAG_REVOKED=0,
+
+  //Subject flag indicates that the subject is a holder of this credential and 
may present it as such
+  GNUNET_CREDENTIAL_FLAG_SUBJECT=1,
+
+  //Issuer flag is used to signify that the subject is allowed to issue this 
credential and delegate issuance
+  GNUNET_CREDENTIAL_FLAG_ISSUER=2
+
+};
+
+GNUNET_NETWORK_STRUCT_BEGIN
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationRecord {
+
+  /**
+   * Number of delegation sets in this record
+   */
+  uint32_t set_count;
+
+  /**
+   * Length of delegation sets
+   */
+  uint64_t data_size;
+  /**
+   * Followed by set_count DelegationSetRecords
+   *
+   */
+};
+
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationRecordSet {
+
+  /**
+   * Public key of the subject this attribute was delegated to
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  /**
+   * Length of attribute, may be 0
+   */
+  uint32_t subject_attribute_len;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * The attribute delegation record
+ */
+struct GNUNET_CREDENTIAL_DelegationSet {
+
+  /**
+   * Public key of the subject this attribute was delegated to
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  uint32_t subject_attribute_len;
+
+  /**
+   * The subject attribute
+   */
+  const char *subject_attribute;
+};
+
+
+/**
+ * A delegation
+ */
+struct GNUNET_CREDENTIAL_Delegation {
+
+  /**
+   * The issuer of the delegation
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * Public key of the subject this attribute was delegated to
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  /**
+   * Length of the attribute
+   */
+  uint32_t issuer_attribute_len;
+
+  /**
+   * The attribute
+   */
+  const char *issuer_attribute;
+
+  /**
+   * Length of the attribute
+   */
+  uint32_t subject_attribute_len;
+
+  /**
+   * The attribute
+   */
+  const char *subject_attribute;
+};
+
+
+/**
+ * A credential
+ */
+struct GNUNET_CREDENTIAL_Credential {
+
+  /**
+   * The issuer of the credential
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * Public key of the subject this credential was issued to
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+
+  /**
+   * Signature of this credential
+   */
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+
+  /**
+   * Expiration of this credential
+   */
+  struct GNUNET_TIME_Absolute expiration;
+
+  /**
+   * Length of the attribute
+   */
+  uint32_t issuer_attribute_len;
+
+  /**
+   * The attribute
+   */
+  const char *issuer_attribute;
+
+};
+
 
 
 /**
@@ -61,7 +212,7 @@ struct GNUNET_CREDENTIAL_LookupRequest;
  * @param cfg configuration to use
  * @return handle to the Credential service, or NULL on error
  */
-struct GNUNET_Credential_Handle *
+struct GNUNET_CREDENTIAL_Handle *
 GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
 
 
@@ -75,73 +226,131 @@ GNUNET_CREDENTIAL_disconnect (struct 
GNUNET_CREDENTIAL_Handle *handle);
 
 
 /**
- * Iterator called on obtained result for a Credential lookup.
+ * Iterator called on obtained result for an attribute verification.
+ *
+ * @param cls closure
+ * @param d_count the number of delegations processed
+ * @param delegation_chain the delegations processed
+ * @param c_count the number of credentials found
+ * @param credential the credentials
+ */
+typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls,
+                                                         unsigned int d_count,
+                                                         struct 
GNUNET_CREDENTIAL_Delegation *delegation_chain,
+                                                         unsigned int c_count,
+                                                         struct 
GNUNET_CREDENTIAL_Credential *credential);
+
+/**
+ * Iterator called on obtained result for an attribute delegation.
+ *
+ * @param cls closure
+ * @param success GNUNET_YES if successful
+ * @param result the record data that can be handed to the subject
+ */
+typedef void (*GNUNET_CREDENTIAL_DelegateResultProcessor) (void *cls,
+                                                           uint32_t success);
+
+/**
+ * Iterator called on obtained result for an attribute delegation removal.
  *
  * @param cls closure
- * @param issuer the issuer chain
- * @param issuer_len length of issuer chain
- * @param value the value returned
+ * @param success GNUNET_YES if successful
+ * @param result the record data that can be handed to the subject
  */
-typedef void
-(*GNUNET_CREDENTIAL_LookupResultProcessor) (void *cls,
-                                            struct GNUNET_IDENTITY_Ego *issuer,
-                                            uint16_t issuer_len,
-                                            const struct 
GNUNET_CREDENTIAL_Value *value);
+typedef void (*GNUNET_CREDENTIAL_RemoveDelegateResultProcessor) (void *cls,
+                                                                 uint32_t 
success);
 
 
 /**
- * Perform an asynchronous lookup operation for a credential.
+ * Performs attribute verification.
+ * Checks if there is a delegation chain from
+ * attribute ``issuer_attribute'' issued by the issuer
+ * with public key ``issuer_key'' maps to the attribute
+ * ``subject_attribute'' claimed by the subject with key
+ * ``subject_key''
  *
  * @param handle handle to the Credential service
- * @param credential the credential to look up
- * @param subject Ego to check the credential for
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param credential_count number of credentials
+ * @param credentials the subject credentials
  * @param proc function to call on result
  * @param proc_cls closure for processor
  * @return handle to the queued request
  */
-struct GNUNET_CREDENTIAL_LookupRequest *
-GNUNET_CREDENTIAL_lookup (struct GNUNET_CREDENTIAL_Handle *handle,
-                          const char *credential,
-                          const struct GNUNET_IDENTITY_Ego *subject,
-                          GNUNET_CREDENTIAL_LookupResultProcessor proc,
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
+                          const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
+                          const char *issuer_attribute,
+                          const struct GNUNET_CRYPTO_EcdsaPublicKey 
*subject_key,
+                          uint32_t credential_count,
+                          const struct GNUNET_CREDENTIAL_Credential 
*credentials,
+                          GNUNET_CREDENTIAL_CredentialResultProcessor proc,
                           void *proc_cls);
 
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
+                           const char *issuer_attribute,
+                           const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*subject_key,
+                           GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+                           void *proc_cls);
 
 /**
- * Issue a credential to an identity
+ * Delegate an attribute
  *
  * @param handle handle to the Credential service
- * @param issuer the identity that issues the credential
- * @param subject the subject of the credential
- * @param credential the name of the credential
- * @param value the value of the credential
+ * @param issuer the ego that should be used to delegate the attribute
+ * @param attribute the name of the attribute to delegate
+ * @param subject the subject of the delegation
+ * @param delegated_attribute the name of the attribute that is delegated to
+ * @param proc the result callback
+ * @param proc_cls the result closure context
  * @return handle to the queued request
  */
-struct GNUNET_CREDENTIAL_IssueRequest *
-GNUNET_CREDENTIAL_issue (struct GNUNET_CREDENTIAL_Handle *handle,
-                         struct GNUNET_IDENTITY_Ego *issuer,
-                         struct GNUNET_IDENTITY_Ego *subject,
-                         const char *credential,
-                         struct GNUNET_CREDENTIAL_Value *value,
-                         GNUNET_CREDENTIAL_IssueResultProcessor proc,
-                         void *proc_cls);
+struct GNUNET_CREDENTIAL_Request *
+GNUNET_CREDENTIAL_add_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
+                                  struct GNUNET_IDENTITY_Ego *issuer,
+                                  const char *attribute,
+                                  struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
+                                  const char *delegated_attribute,
+                                  GNUNET_CREDENTIAL_DelegateResultProcessor 
proc,
+                                  void *proc_cls);
 
 /**
- * Remove a credential
+ * Remove a delegation
  *
  * @param handle handle to the Credential service
- * @param issuer the identity that issued the credential
- * @param subject the subject of the credential
- * @param credential the name of the credential
+ * @param issuer the ego that was used to delegate the attribute
+ * @param attribute the name of the attribute that is delegated
+ * @param proc the callback
+ * @param proc_cls callback closure
  * @return handle to the queued request
  */
-struct GNUNET_CREDENTIAL_IssueRequest *
-GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle *handle,
-                          struct GNUNET_IDENTITY_Ego *issuer,
-                          struct GNUNET_IDENTITY_Ego *subject,
-                          const char *credential,
-                          GNUNET_CREDENTIAL_IssueResultProcessor proc,
-                          void *proc_cls);
+struct GNUNET_CREDENTIAL_Request *
+GNUNET_CREDENTIAL_remove_delegation (struct GNUNET_CREDENTIAL_Handle *handle,
+                                     struct GNUNET_IDENTITY_Ego *issuer,
+                                     const char *attribute,
+                                     
GNUNET_CREDENTIAL_RemoveDelegateResultProcessor proc,
+                                     void *proc_cls);
+
+
+
+/**
+ * Issue an attribute to a subject
+ *
+ * @param issuer the ego that should be used to issue the attribute
+ * @param subject the subject of the attribute
+ * @param attribute the name of the attribute
+ * @param expiration the TTL of the credential
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*issuer,
+                                    struct GNUNET_CRYPTO_EcdsaPublicKey 
*subject,
+                                    const char *attribute,
+                                    struct GNUNET_TIME_Absolute *expiration);
 
 
 
@@ -151,7 +360,7 @@ GNUNET_CREDENTIAL_remove (struct GNUNET_CREDENTIAL_Handle 
*handle,
  * @param lr the lookup request to cancel
  */
 void
-GNUNET_CREDENTIAL_lookup_cancel (struct GNUNET_CREDENTIAL_LookupRequest *lr);
+GNUNET_CREDENTIAL_request_cancel (struct GNUNET_CREDENTIAL_Request *lr);
 
 
 #if 0                           /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_gnsrecord_lib.h 
b/src/include/gnunet_gnsrecord_lib.h
index 985ae1f7a..d03b4db3b 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -109,9 +109,29 @@ extern "C"
 #define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546
 
 /**
+ * Record type for credential
+ */
+#define GNUNET_GNSRECORD_TYPE_CREDENTIAL 65547
+
+/**
+ * Record type for policies
+ */
+#define GNUNET_GNSRECORD_TYPE_POLICY 65548
+
+/**
  * Record type for reverse lookups
  */
-#define GNUNET_GNSRECORD_TYPE_REVERSE 65548
+#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549
+
+/**
+ * Record type for ABE records
+ */
+#define GNUNET_GNSRECORD_TYPE_ABE_KEY 65550
+
+/**
+ * Record type for ABE master keys
+ */
+#define GNUNET_GNSRECORD_TYPE_ABE_MASTER 65551
 
 /**
  * Flags that can be set for a record.
diff --git a/src/include/gnunet_identity_attribute_lib.h 
b/src/include/gnunet_identity_attribute_lib.h
new file mode 100644
index 000000000..316b0bf95
--- /dev/null
+++ b/src/include/gnunet_identity_attribute_lib.h
@@ -0,0 +1,277 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @author Martin Schanzenbach
+ *
+ * @file
+ * Identity attribute definitions
+ *
+ * @defgroup identity-provider  Identity Provider service
+ * @{
+ */
+#ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H
+#define GNUNET_IDENTITY_ATTRIBUTE_LIB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_util_lib.h"
+
+
+/**
+ * No value attribute.
+ */
+#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_NONE 0
+
+/**
+ * String attribute.
+ */
+#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING 1
+
+
+
+/**
+ * An attribute.
+ */
+struct GNUNET_IDENTITY_ATTRIBUTE_Claim
+{
+  /**
+   * The name of the attribute. Note "name" must never be individually
+   * free'd
+   */
+  const char* name;
+
+  /**
+   * Type of Claim
+   */
+  uint32_t type;
+
+  /**
+   * Version
+   */
+  uint32_t version;
+
+  /**
+   * Number of bytes in @e data.
+   */
+  size_t data_size;
+
+  /**
+   * Binary value stored as attribute value.  Note: "data" must never
+   * be individually 'malloc'ed, but instead always points into some
+   * existing data area.
+   */
+  const void *data;
+
+};
+
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList
+{
+  /**
+   * List head
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_head;
+
+  /**
+   * List tail
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_tail;
+};
+
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry
+{
+  /**
+   * DLL
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *prev;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *next;
+
+  /**
+   * The attribute claim
+   */
+  struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
+};
+
+/**
+ * Create a new attribute claim.
+ *
+ * @param attr_name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
+GNUNET_IDENTITY_ATTRIBUTE_claim_new (const char* attr_name,
+                                     uint32_t type,
+                                     const void* data,
+                                     size_t data_size);
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attrs the attribute list to serialize
+ *
+ * @return the required buffer size
+ */
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
+
+void
+GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
+
+
+/**
+ * Serialize an attribute list
+ *
+ * @param attrs the attribute list to serialize
+ * @param result the serialized attribute
+ *
+ * @return length of serialized data
+ */
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+                     char *result);
+
+/**
+ * Deserialize an attribute list
+ *
+ * @param data the serialized attribute list
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
+ */
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *
+GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data,
+                            size_t data_size);
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the attribute to serialize
+ *
+ * @return the required buffer size
+ */
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct 
GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
+
+
+
+/**
+ * Serialize an attribute
+ *
+ * @param attr the attribute to serialize
+ * @param result the serialized attribute
+ *
+ * @return length of serialized data
+ */
+size_t
+GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct 
GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
+                     char *result);
+
+/**
+ * Deserialize an attribute
+ *
+ * @param data the serialized attribute
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_IDENTITY_ATTRIBUTE_Claim *
+GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data,
+                       size_t data_size);
+
+struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList*
+GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
+
+/**
+ * Convert a type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (const char *typename);
+
+/**
+ * Convert human-readable version of a 'claim' of an attribute to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_ATTRIBUTE_string_to_value (uint32_t type,
+                                           const char *s,
+                                           void **data,
+                                           size_t *data_size);
+
+/**
+ * Convert the 'claim' of an attribute to a string
+ *
+ * @param type the type of attribute
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type,
+                                           const void* data,
+                                           size_t data_size);
+
+/**
+ * Convert a type number to the corresponding type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char*
+GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H */
+#endif
+
+/** @} */ /* end of group identity */
+
+/* end of gnunet_identity_attribute_lib.h */
diff --git a/src/include/gnunet_gnsrecord_plugin.h 
b/src/include/gnunet_identity_attribute_plugin.h
similarity index 69%
copy from src/include/gnunet_gnsrecord_plugin.h
copy to src/include/gnunet_identity_attribute_plugin.h
index d212c3663..edeed57fd 100644
--- a/src/include/gnunet_gnsrecord_plugin.h
+++ b/src/include/gnunet_identity_attribute_plugin.h
@@ -19,20 +19,20 @@
 */
 
 /**
- * @author Christian Grothoff
+ * @author Martin Schanzenbach
  *
  * @file
- * Plugin API for GNS record types
- *
- * @defgroup gnsrecord-plugin  GNS Record plugin API
- * To be implemented by applications defining new record types.
- *
- * @see [Documentation](https://gnunet.org/gns-plugins)
+ * Plugin API for the idp database backend
  *
+ * @defgroup identity-provider-plugin  IdP service plugin API
+ * Plugin API for the idp database backend
  * @{
  */
-#ifndef GNUNET_GNSRECORD_PLUGIN_H
-#define GNUNET_GNSRECORD_PLUGIN_H
+#ifndef GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
+#define GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet_identity_attribute_lib.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -44,16 +44,16 @@ extern "C"
 
 
 /**
- * Function called to convert the binary value @a data of a record of
+ * Function called to convert the binary value @a data of an attribute of
  * type @a type to a human-readable string.
  *
  * @param cls closure
- * @param type type of the record
+ * @param type type of the attribute
  * @param data value in binary encoding
  * @param data_size number of bytes in @a data
  * @return NULL on error, otherwise human-readable representation of the value
  */
-typedef char * (*GNUNET_GNSRECORD_ValueToStringFunction) (void *cls,
+typedef char * (*GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction) (void *cls,
                                                           uint32_t type,
                                                           const void *data,
                                                           size_t data_size);
@@ -61,17 +61,17 @@ typedef char * (*GNUNET_GNSRECORD_ValueToStringFunction) 
(void *cls,
 
 /**
  * Function called to convert human-readable version of the value @a s
- * of a record of type @a type to the respective binary
+ * of an attribute of type @a type to the respective binary
  * representation.
  *
  * @param cls closure
- * @param type type of the record
+ * @param type type of the attribute
  * @param s human-readable string
  * @param data set to value in binary encoding (will be allocated)
  * @param data_size set to number of bytes in @a data
  * @return #GNUNET_OK on success
  */
-typedef int (*GNUNET_GNSRECORD_StringToValueFunction) (void *cls,
+typedef int (*GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction) (void *cls,
                                                        uint32_t type,
                                                        const char *s,
                                                        void **data,
@@ -79,26 +79,26 @@ typedef int (*GNUNET_GNSRECORD_StringToValueFunction) (void 
*cls,
 
 
 /**
- * Function called to convert a type name (i.e. "AAAA") to the
+ * Function called to convert a type name to the
  * corresponding number.
  *
  * @param cls closure
- * @param dns_typename name to convert
+ * @param typename name to convert
  * @return corresponding number, UINT32_MAX on error
  */
-typedef uint32_t (*GNUNET_GNSRECORD_TypenameToNumberFunction) (void *cls,
-                                                               const char 
*dns_typename);
+typedef uint32_t (*GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction) (void 
*cls,
+                                                               const char 
*typename);
 
 
 /**
  * Function called to convert a type number (i.e. 1) to the
- * corresponding type string (i.e. "A")
+ * corresponding type string
  *
  * @param cls closure
  * @param type number of a type to convert
  * @return corresponding typestring, NULL on error
  */
-typedef const char * (*GNUNET_GNSRECORD_NumberToTypenameFunction) (void *cls,
+typedef const char * (*GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction) 
(void *cls,
                                                                    uint32_t 
type);
 
 
@@ -106,7 +106,7 @@ typedef const char * 
(*GNUNET_GNSRECORD_NumberToTypenameFunction) (void *cls,
  * Each plugin is required to return a pointer to a struct of this
  * type as the return value from its entry point.
  */
-struct GNUNET_GNSRECORD_PluginFunctions
+struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions
 {
 
   /**
@@ -117,26 +117,25 @@ struct GNUNET_GNSRECORD_PluginFunctions
   /**
    * Conversion to string.
    */
-  GNUNET_GNSRECORD_ValueToStringFunction value_to_string;
+  GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction value_to_string;
 
   /**
    * Conversion to binary.
    */
-  GNUNET_GNSRECORD_StringToValueFunction string_to_value;
+  GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction string_to_value;
 
   /**
    * Typename to number.
    */
-  GNUNET_GNSRECORD_TypenameToNumberFunction typename_to_number;
+  GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction typename_to_number;
 
   /**
    * Number to typename.
    */
-  GNUNET_GNSRECORD_NumberToTypenameFunction number_to_typename;
+  GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction number_to_typename;
 
 };
 
-/** @} */  /* end of group */
 
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
@@ -146,3 +145,5 @@ struct GNUNET_GNSRECORD_PluginFunctions
 #endif
 
 #endif
+
+/** @} */  /* end of group */
diff --git a/src/include/gnunet_identity_provider_plugin.h 
b/src/include/gnunet_identity_provider_plugin.h
new file mode 100644
index 000000000..4b5098d58
--- /dev/null
+++ b/src/include/gnunet_identity_provider_plugin.h
@@ -0,0 +1,123 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2012, 2013 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @author Martin Schanzenbach
+ *
+ * @file
+ * Plugin API for the idp database backend
+ *
+ * @defgroup identity-provider-plugin  IdP service plugin API
+ * Plugin API for the idp database backend
+ * @{
+ */
+#ifndef GNUNET_IDENTITY_PROVIDER_PLUGIN_H
+#define GNUNET_IDENTITY_PROVIDER_PLUGIN_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet_identity_provider_service.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * Function called by for each matching ticket.
+ *
+ * @param cls closure
+ * @param ticket the ticket
+ */
+typedef void (*GNUNET_IDENTITY_PROVIDER_TicketIterator) (void *cls,
+                                                const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+             const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
+
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct GNUNET_IDENTITY_PROVIDER_PluginFunctions
+{
+
+  /**
+   * Closure to pass to all plugin functions.
+   */
+  void *cls;
+
+  /**
+   * Store a ticket in the database.
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param ticket the ticket to store
+   * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+   */
+  int (*store_ticket) (void *cls,
+                       const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+      const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
+
+  /**
+   * Delete a ticket from the database.
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param ticket the ticket to store
+   * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+   */
+  int (*delete_ticket) (void *cls,
+                       const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
+
+
+
+  /**
+   * Iterate over all tickets
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param identity the identity
+   * @param audience GNUNET_YES if the identity is the audience of the ticket
+   *                 else it is considered the issuer
+   * @param iter function to call with the result
+   * @param iter_cls closure for @a iter
+   * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, 
#GNUNET_SYSERR on error
+   */
+  int (*iterate_tickets) (void *cls,
+                         const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+        int audience,
+                         uint64_t offset,
+                         GNUNET_IDENTITY_PROVIDER_TicketIterator iter, void 
*iter_cls);
+
+  int (*get_ticket_attributes) (void* cls,
+                                const struct GNUNET_IDENTITY_PROVIDER_Ticket 
*ticket,
+                                GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+                                void *iter_cls);
+};
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/** @} */  /* end of group */
diff --git a/src/include/gnunet_identity_provider_service.h 
b/src/include/gnunet_identity_provider_service.h
index e533f6f8c..be935e898 100644
--- a/src/include/gnunet_identity_provider_service.h
+++ b/src/include/gnunet_identity_provider_service.h
@@ -39,7 +39,7 @@ extern "C"
 #endif
 
 #include "gnunet_util_lib.h"
-
+#include "gnunet_identity_attribute_lib.h"
 
 /**
  * Version number of GNUnet Identity Provider API.
@@ -57,169 +57,310 @@ struct GNUNET_IDENTITY_PROVIDER_Handle;
 struct GNUNET_IDENTITY_PROVIDER_Token;
 
 /**
- * Handle for a ticket
+ * The ticket
  */
-struct GNUNET_IDENTITY_PROVIDER_Ticket;
+struct GNUNET_IDENTITY_PROVIDER_Ticket
+{
+  /**
+   * The ticket issuer
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /**
+   * The ticket audience
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey audience;
+
+  /**
+   * The ticket random (NBO)
+   */
+  uint64_t rnd;
+};
 
 /**
  * Handle for an operation with the identity provider service.
  */
 struct GNUNET_IDENTITY_PROVIDER_Operation;
 
+
 /**
- * Method called when a token has been exchanged for a ticket.
- * On success returns a token
+ * Connect to the identity provider service.
  *
- * @param cls closure
- * @param token the token
+ * @param cfg Configuration to contact the identity provider service.
+ * @return handle to communicate with identity provider service
  */
-typedef void
-(*GNUNET_IDENTITY_PROVIDER_ExchangeCallback)(void *cls,
-                            const struct GNUNET_IDENTITY_PROVIDER_Token *token,
-                            uint64_t ticket_nonce);
+struct GNUNET_IDENTITY_PROVIDER_Handle *
+GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle 
*cfg);
 
 /**
- * Method called when a token has been issued.
- * On success returns a ticket that can be given to the audience to retrive the
- * token
+ * Continuation called to notify client about result of the
+ * operation.
  *
  * @param cls closure
- * @param grant the label in GNS pointing to the token
- * @param ticket the ticket
- * @param token the issued token
- * @param name name assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
+ * @param success #GNUNET_SYSERR on failure (including timeout/queue 
drop/failure to validate)
+ *                #GNUNET_NO if content was already there or not found
+ *                #GNUNET_YES (or other positive value) on success
+ * @param emsg NULL on success, otherwise an error message
  */
 typedef void
-(*GNUNET_IDENTITY_PROVIDER_IssueCallback)(void *cls,
-                            const char *grant,
-                            const struct GNUNET_IDENTITY_PROVIDER_Ticket 
*ticket,
-                            const struct GNUNET_IDENTITY_PROVIDER_Token 
*token);
+(*GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus) (void *cls,
+                                            int32_t success,
+                                            const char *emsg);
 
 
 /**
- * Connect to the identity provider service.
+ * Store an attribute.  If the attribute is already present,
+ * it is replaced with the new attribute.
  *
- * @param cfg Configuration to contact the identity provider service.
- * @return handle to communicate with identity provider service
+ * @param h handle to the identity provider
+ * @param pkey private key of the identity
+ * @param attr the attribute
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
  */
-struct GNUNET_IDENTITY_PROVIDER_Handle *
-GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle 
*cfg);
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_attribute_store (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                          const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+                                          const struct 
GNUNET_IDENTITY_ATTRIBUTE_Claim *attr,
+                                          
GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
+                                          void *cont_cls);
 
 
 /**
- * Issue a token for a specific audience.
+ * Process an attribute that was stored in the idp.
  *
- * @param id identity provider service to use
- * @param iss issuer (identity)
- * @param aud audience (identity)
- * @param scope the identity attributes requested, comman separated
- * @param expiration the token expiration
- * @param nonce the nonce that will be included in token and ticket
- * @param cb callback to call with result
- * @param cb_cls closure
- * @return handle to abort the operation
+ * @param cls closure
+ * @param identity the identity
+ * @param attr the attribute
  */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle 
*id,
-                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
-         const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-         const char* scope,
-         struct GNUNET_TIME_Absolute expiration,
-         uint64_t nonce,
-                    GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
-                    void *cb_cls);
+typedef void
+(*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls,
+                                   const struct GNUNET_CRYPTO_EcdsaPublicKey 
*identity,
+                                   const struct 
GNUNET_IDENTITY_ATTRIBUTE_Claim *attr);
+
 
 
 /**
- * Exchange a ticket for a token. Intended to be used by audience that
- * received a ticket.
+ * List all attributes for a local identity. 
+ * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
+ * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked.
  *
- * @param id identity provider service to use
- * @param ticket the ticket to exchange
- * @param aud_privkey the audience of the ticket
- * @param cont function to call once the operation finished
- * @param cont_cls closure for @a cont
- * @return handle to abort the operation
+ * On error (disconnect), @a error_cb will be invoked.
+ * On normal completion, @a finish_cb proc will be
+ * invoked.
+ *
+ * @param h handle to the idp
+ * @param identity identity to access
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each attribute; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
  */
-struct GNUNET_IDENTITY_PROVIDER_Operation *
-GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
-                    const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-         const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
-                    GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
-                    void *cont_cls);
+struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *
+GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                               const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                               GNUNET_SCHEDULER_TaskCallback 
error_cb,
+                                               void *error_cb_cls,
+                                               
GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
+                                               void *proc_cls,
+                                               GNUNET_SCHEDULER_TaskCallback 
finish_cb,
+                                               void *finish_cb_cls);
 
 
 /**
- * Disconnect from identity provider service.
+ * Calls the record processor specified in 
#GNUNET_IDENTITY_PROVIDER_get_attributes_start
+ * for the next record.
  *
- * @param h identity provider service to disconnect
+ * @param it the iterator
  */
 void
-GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle 
*h);
+GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct 
GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
 
 
 /**
- * Cancel an identity provider operation.  Note that the operation MAY still
- * be executed; this merely cancels the continuation; if the request
- * was already transmitted, the service may still choose to complete
- * the operation.
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
  *
- * @param op operation to cancel
+ * @param it the iterator
  */
 void
-GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation 
*op);
+GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct 
GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
 
 
 /**
- * Convenience API
+ * Method called when a token has been issued.
+ * On success returns a ticket that can be given to the audience to retrive the
+ * token
+ *
+ * @param cls closure
+ * @param ticket the ticket
  */
+typedef void
+(*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls,
+                            const struct GNUNET_IDENTITY_PROVIDER_Ticket 
*ticket);
 
 /**
- * Destroy token
+ * Issues a ticket to another identity. The identity may use
+ * GNUNET_IDENTITY_PROVIDER_ticket_consume to consume the ticket
+ * and retrieve the attributes specified in the AttributeList.
  *
- * @param token the token
+ * @param h the identity provider to use
+ * @param iss the issuing identity
+ * @param rp the subject of the ticket (the relying party)
+ * @param attrs the attributes that the relying party is given access to
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
  */
-void
-GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token 
*token);
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle 
*h,
+                                       const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *iss,
+                                       const struct 
GNUNET_CRYPTO_EcdsaPublicKey *rp,
+                                       const struct 
GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
+                                       GNUNET_IDENTITY_PROVIDER_TicketCallback 
cb,
+                                       void *cb_cls);
 
 /**
- * Returns string representation of token. A JSON-Web-Token.
+ * Revoked an issued ticket. The relying party will be unable to retrieve
+ * updated attributes.
  *
- * @param token the token
- * @return The JWT (must be freed)
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param ticket the ticket to revoke
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
  */
-char *
-GNUNET_IDENTITY_PROVIDER_token_to_string (const struct 
GNUNET_IDENTITY_PROVIDER_Token *token);
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle 
*h,
+                                        const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                        const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                        
GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
+                                        void *cb_cls);
+
+
 
 /**
- * Returns string representation of ticket. Base64-Encoded
+ * Consumes an issued ticket. The ticket is persisted
+ * and used to retrieve identity information from the issuer
  *
- * @param ticket the ticket
- * @return the Base64-Encoded ticket
+ * @param h the identity provider to use
+ * @param identity the identity that is the subject of the issued ticket (the 
audience)
+ * @param ticket the issued ticket to consume
+ * @param cb the callback to call
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_ticket_consume (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                         const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                         const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                         
GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
+                                         void *cb_cls);
+
+/**
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
+ *
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
+ */
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                                 const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                                 GNUNET_SCHEDULER_TaskCallback 
error_cb,
+                                                 void *error_cb_cls,
+                                                 
GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
+                                                 void *proc_cls,
+                                                 GNUNET_SCHEDULER_TaskCallback 
finish_cb,
+                                                 void *finish_cb_cls);
+
+/**
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
+ *
+ * @param h the identity provider to use
+ * @param identity the issuing identity
+ * @param error_cb function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls closure for @a error_cb
+ * @param proc function to call on each ticket; it
+ *        will be called repeatedly with a value (if available)
+ * @param proc_cls closure for @a proc
+ * @param finish_cb function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls closure for @a finish_cb
+ * @return an iterator handle to use for iteration
  */
-char *
-GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket);
+struct GNUNET_IDENTITY_PROVIDER_TicketIterator *
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                                    const struct 
GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                                                    
GNUNET_SCHEDULER_TaskCallback error_cb,
+                                                    void *error_cb_cls,
+                                                    
GNUNET_IDENTITY_PROVIDER_TicketCallback proc,
+                                                    void *proc_cls,
+                                                    
GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                                    void *finish_cb_cls);
 
 /**
- * Created a ticket from a string (Base64 encoded ticket)
+ * Calls the record processor specified in 
#GNUNET_IDENTITY_PROVIDER_ticket_iteration_start
+ * for the next record.
  *
- * @param input Base64 encoded ticket
- * @param ticket pointer where the ticket is stored
- * @return GNUNET_OK
+ * @param it the iterator
  */
-int
-GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input,
-                                           struct 
GNUNET_IDENTITY_PROVIDER_Ticket **ticket);
+void
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct 
GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
 
 /**
- * Destroys a ticket
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
  *
- * @param ticket the ticket to destroy
+ * @param it the iterator
  */
 void
-GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket 
*ticket);
+GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct 
GNUNET_IDENTITY_PROVIDER_TicketIterator *it);
+
+/**
+ * Disconnect from identity provider service.
+ *
+ * @param h identity provider service to disconnect
+ */
+void
+GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle 
*h);
+
+
+/**
+ * Cancel an identity provider operation.  Note that the operation MAY still
+ * be executed; this merely cancels the continuation; if the request
+ * was already transmitted, the service may still choose to complete
+ * the operation.
+ *
+ * @param op operation to cancel
+ */
+void
+GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation 
*op);
 
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
diff --git a/src/include/gnunet_jsonapi_lib.h b/src/include/gnunet_jsonapi_lib.h
index f95bff836..2f6b810f0 100644
--- a/src/include/gnunet_jsonapi_lib.h
+++ b/src/include/gnunet_jsonapi_lib.h
@@ -248,7 +248,7 @@ GNUNET_JSONAPI_resource_check_id (const struct 
GNUNET_JSONAPI_Resource *resource
  * @param res the JSON resource
  * @return the resource id
  */
-char*
+const char*
 GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource 
*resource);
 
 
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 9cfd00e39..436adc5a4 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2628,13 +2628,47 @@ extern "C"
  *
  * IDENTITY PROVIDER MESSAGE TYPES
  */
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE     961
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE 961
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE  962
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 962
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT     963
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START 963
 
-#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT  964
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP 964
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT 965
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 966
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET 967
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 968
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET 969
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT 970
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 971
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 972
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 973
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 974
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 975
+
+/**************************************************
+ *
+ * CREDENTIAL MESSAGE TYPES
+ */
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY     981
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 982
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 983
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 984
 
 
/******************************************************************************/
 
diff --git a/src/include/gnunet_rest_lib.h b/src/include/gnunet_rest_lib.h
index a4dbb0696..e571eead3 100644
--- a/src/include/gnunet_rest_lib.h
+++ b/src/include/gnunet_rest_lib.h
@@ -89,7 +89,7 @@ typedef void (*GNUNET_REST_ResultProcessor) (void *cls,
  *
  * @param url URL to check
  * @param namespace namespace to check against
- * @retun GNUNET_YES if namespace matches
+ * @return GNUNET_YES if namespace matches
  */
 int
 GNUNET_REST_namespace_match (const char *url, const char *namespace);
@@ -98,7 +98,7 @@ GNUNET_REST_namespace_match (const char *url, const char 
*namespace);
  * Create REST MHD response
  *
  * @param data result
- * @retun MHD response
+ * @return MHD response
  */
  struct MHD_Response*
 GNUNET_REST_create_response (const char *data);
diff --git a/src/include/gnunet_rest_plugin.h b/src/include/gnunet_rest_plugin.h
index ecd5f66f1..424dbb1fc 100644
--- a/src/include/gnunet_rest_plugin.h
+++ b/src/include/gnunet_rest_plugin.h
@@ -57,7 +57,7 @@ struct GNUNET_REST_Plugin
 
   /**
    * Plugin name. Used as the namespace for the API.
-   * e.g. http://hostname:port/<name>
+   * e.g. http://hostname:port/name
    */
   char *name;
 
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index c1e0d005c..03bc4575e 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -185,6 +185,11 @@ extern "C"
  */
 #define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27
 
+/**
+ * Signature for a GNUnet credential
+ */
+#define GNUNET_SIGNATURE_PURPOSE_CREDENTIAL 28
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
diff --git a/src/jsonapi/jsonapi_document.c b/src/jsonapi/jsonapi_document.c
index 600b7ee6a..3a60940f6 100644
--- a/src/jsonapi/jsonapi_document.c
+++ b/src/jsonapi/jsonapi_document.c
@@ -332,28 +332,20 @@ GNUNET_JSONAPI_document_to_json (const struct 
GNUNET_JSONAPI_Document *doc,
                          GNUNET_JSONAPI_KEY_ERRORS,
                          res_json);
   } else {
-    switch (doc->res_count)
+    if (0 == doc->res_count)
     {
-      case 0:
-        res_json = json_null();
-        break;
-      case 1:
+      res_json = json_null();
+    } else {
+      res_json = json_array ();
+      for (res = doc->res_list_head;
+           res != NULL;
+           res = res->next)
+      {
         GNUNET_assert (GNUNET_OK ==
-                       GNUNET_JSONAPI_resource_to_json (doc->res_list_head,
-                                                        &res_json));
-        break;
-      default:
-        res_json = json_array ();
-        for (res = doc->res_list_head;
-             res != NULL;
-             res = res->next)
-        {
-          GNUNET_assert (GNUNET_OK ==
-                         GNUNET_JSONAPI_resource_to_json (res,
-                                                          &res_json_tmp));
-          json_array_append (res_json, res_json_tmp);
-        }
-        break;
+                       GNUNET_JSONAPI_resource_to_json (res,
+                                                        &res_json_tmp));
+        json_array_append_new (res_json, res_json_tmp);
+      }
     }
     json_object_set_new (*root_json,
                          GNUNET_JSONAPI_KEY_DATA,
diff --git a/src/jsonapi/jsonapi_resource.c b/src/jsonapi/jsonapi_resource.c
index 85bca10ee..be28ad5df 100644
--- a/src/jsonapi/jsonapi_resource.c
+++ b/src/jsonapi/jsonapi_resource.c
@@ -92,9 +92,9 @@ GNUNET_JSONAPI_resource_new (const char *type, const char *id)
 {
   struct GNUNET_JSONAPI_Resource *res;
 
-  if ( (NULL == type) || (0 == strlen (type)) )
+  if (NULL == type)
     return NULL;
-  if ( (NULL == id) || (0 == strlen (id)) )
+  if (NULL == id)
     return NULL;
 
   res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
@@ -245,7 +245,7 @@ GNUNET_JSONAPI_resource_check_id (const struct 
GNUNET_JSONAPI_Resource *resource
  * @param res the JSON resource
  * @return the resource id
  */
-char*
+const char*
 GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource)
 {
   return resource->id;
diff --git a/src/namestore/plugin_rest_namestore.c 
b/src/namestore/plugin_rest_namestore.c
index 50957a5b4..05776801b 100644
--- a/src/namestore/plugin_rest_namestore.c
+++ b/src/namestore/plugin_rest_namestore.c
@@ -401,11 +401,16 @@ namestore_list_finished (void *cls)
   struct MHD_Response *resp;
 
   handle->list_it = NULL;
+  if (NULL == handle->resp_object)
+    handle->resp_object = GNUNET_JSONAPI_document_new ();
+
   if (GNUNET_SYSERR ==
       GNUNET_JSONAPI_document_serialize (handle->resp_object,
                                          &result))
   {
-    do_error (handle);
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error,
+                              handle);
     return;
   }
   resp = GNUNET_REST_create_response (result);
@@ -467,10 +472,10 @@ namestore_list_response (void *cls,
   if (0 < json_array_size(result_array))
   {
     json_resource = GNUNET_JSONAPI_resource_new 
(GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
-                                                      rname);
+                                                 rname);
     GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                           
GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
-                                           result_array);
+                                      GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
+                                      result_array);
     GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
   }
 
@@ -767,8 +772,8 @@ namestore_create_cont (struct GNUNET_REST_RequestHandle 
*con,
   }
   term_data[handle->rest_handle->data_size] = '\0';
   GNUNET_memcpy (term_data,
-          handle->rest_handle->data,
-          handle->rest_handle->data_size);
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
   data_js = json_loads (term_data,
                         JSON_DECODE_ANY,
                         &err);
@@ -902,7 +907,7 @@ namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con,
   if ((NULL == handle->zkey_str) ||
       (GNUNET_OK !=
        GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str,
-                                                  strlen (handle->zkey_str),
+                                                   strlen (handle->zkey_str),
                                                    &pubkey)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1021,13 +1026,13 @@ identity_cb (void *cls,
 
   if (GNUNET_OK !=
       GNUNET_JSONAPI_handle_request (handle->rest_handle,
-                                    handlers,
-                                    &err,
-                                    handle))
+                                     handlers,
+                                     &err,
+                                     handle))
   {
     handle->response_code = err.error_code;
     GNUNET_SCHEDULER_add_now (&do_error,
-                             (void *) handle);
+                              (void *) handle);
   }
 }
 
diff --git a/src/rest/rest.conf b/src/rest/rest.conf
index 6cd013345..b86e6c1a0 100644
--- a/src/rest/rest.conf
+++ b/src/rest/rest.conf
@@ -1,4 +1,5 @@
 [rest]
+UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-rest.sock
 BINARY=gnunet-rest-server
 REST_PORT=7776
 REST_ALLOW_HEADERS=Authorization,Accept,Content-Type
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index c26e3e84b..eb655157d 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -123,7 +123,6 @@ libgnunetutil_la_LDFLAGS = \
   $(GN_LIB_LDFLAGS) \
   -version-info 13:0:0
 
-
 libgnunetutil_taler_wallet_la_SOURCES = \
   common_allocation.c \
   common_endian.c \
diff --git a/src/util/crypto_abe.c b/src/util/crypto_abe.c
new file mode 100644
index 000000000..fcaa826ed
--- /dev/null
+++ b/src/util/crypto_abe.c
@@ -0,0 +1,416 @@
+/*
+     This file is part of GNUnet.  Copyright (C) 2001-2014 Christian Grothoff
+     (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+
+*/
+
+/**
+ * @file util/crypto_random.c
+ * @brief functions to gather random numbers
+ * @author Christian Grothoff
+ */
+
+
+#include "platform.h"
+#include <pbc/pbc.h>
+#include <gabe.h>
+
+#include "gnunet_crypto_lib.h"
+
+struct GNUNET_CRYPTO_AbeMasterKey
+{
+  gabe_pub_t* pub;
+  gabe_msk_t* msk;
+};
+
+struct GNUNET_CRYPTO_AbeKey
+{
+  gabe_pub_t* pub;
+  gabe_prv_t* prv;
+};
+
+static int
+init_aes( element_t k, int enc,
+          gcry_cipher_hd_t* handle,
+          struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+          unsigned char* iv)
+{
+  int rc;
+  int key_len;
+  unsigned char* key_buf;
+  
+  key_len = element_length_in_bytes(k) < 33 ? 3 : element_length_in_bytes(k);
+  key_buf = (unsigned char*) malloc(key_len);
+  element_to_bytes(key_buf, k);
+
+  memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH); 
+  GNUNET_assert (0 ==
+                 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
+                                   GCRY_CIPHER_MODE_CFB, 0));
+  rc = gcry_cipher_setkey (*handle,
+                           key->aes_key,
+                           sizeof (key->aes_key));
+  GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+  memset (iv, 0, 16); //TODO make reasonable
+  rc = gcry_cipher_setiv (*handle,
+                          iv,
+                          16);
+  GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+
+  free(key_buf);
+  return rc;
+}
+
+static int
+aes_128_cbc_encrypt( char* pt,
+                     int size,
+                     element_t k,
+                     char **ct )
+{
+  gcry_cipher_hd_t handle;
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  unsigned char iv[16];
+  char* buf;
+  int padding;
+  int buf_size;
+  uint8_t len[4];
+  init_aes(k, 1, &handle, &skey, iv);
+
+  /* TODO make less crufty */
+
+  /* stuff in real length (big endian) before padding */
+  len[0] = (size & 0xff000000)>>24;
+  len[1] = (size & 0xff0000)>>16;
+  len[2] = (size & 0xff00)>>8;
+  len[3] = (size & 0xff)>>0;
+  padding = 16 - ((4+size) % 16);
+  buf_size = 4 + size + padding;
+  buf = GNUNET_malloc (buf_size);
+  GNUNET_memcpy (buf, len, 4);
+  GNUNET_memcpy (buf+4, pt, size);
+  *ct = GNUNET_malloc (buf_size);
+
+  GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf, 
buf_size));
+  gcry_cipher_close (handle);
+  //AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
+  GNUNET_free (buf);
+  return buf_size;
+}
+
+static int
+aes_128_cbc_decrypt( char* ct,
+                     int size,
+                     element_t k,
+                     char **pt )
+{
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  gcry_cipher_hd_t handle;
+  unsigned char iv[16];
+  char* tmp;
+  uint32_t len;
+  
+  init_aes(k, 1, &handle, &skey, iv);
+
+  tmp = GNUNET_malloc (size);
+
+  //AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
+  GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size)); 
+  gcry_cipher_close (handle);
+  /* TODO make less crufty */
+  
+  /* get real length */
+  len = 0;
+  len = len
+    | ((tmp[0])<<24) | ((tmp[1])<<16)
+    | ((tmp[2])<<8)  | ((tmp[3])<<0);
+  /* truncate any garbage from the padding */
+  *pt = GNUNET_malloc (len);
+  GNUNET_memcpy (*pt, tmp+4, len);
+  GNUNET_free (tmp);
+  return len;
+}
+
+struct GNUNET_CRYPTO_AbeMasterKey*
+GNUNET_CRYPTO_cpabe_create_master_key (void)
+{
+  struct GNUNET_CRYPTO_AbeMasterKey* key;
+  key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
+  gabe_setup(&key->pub, &key->msk);
+  GNUNET_assert (NULL != key->pub);
+  GNUNET_assert (NULL != key->msk);
+  return key;
+}
+
+void
+GNUNET_CRYPTO_cpabe_delete_master_key (struct GNUNET_CRYPTO_AbeMasterKey *key)
+{
+  gabe_msk_free (key->msk);
+  gabe_pub_free (key->pub);
+  //GNUNET_free (key->msk);
+  //gabe_msk_free (key->msk); //For some reason free of pub implicit?
+  GNUNET_free (key);
+}
+
+struct GNUNET_CRYPTO_AbeKey*
+GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *key,
+                             char **attrs)
+{
+  struct GNUNET_CRYPTO_AbeKey *prv_key;
+  int size;
+  char *tmp;
+  
+  prv_key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
+  prv_key->prv = gabe_keygen(key->pub, key->msk, attrs);
+  size = gabe_pub_serialize(key->pub, &tmp);
+  prv_key->pub = gabe_pub_unserialize(tmp, size);
+  GNUNET_free (tmp);
+  GNUNET_assert (NULL != prv_key->prv);
+  return prv_key;
+}
+
+void
+GNUNET_CRYPTO_cpabe_delete_key (struct GNUNET_CRYPTO_AbeKey *key,
+                                int delete_pub)
+{
+  //Memory management in gabe is buggy
+  gabe_prv_free (key->prv);
+  if (GNUNET_YES == delete_pub)
+    gabe_pub_free (key->pub);
+  GNUNET_free (key);
+}
+
+ssize_t
+write_cpabe (void **result,
+             uint32_t file_len,
+             char* cph_buf,
+             int cph_buf_len,
+             char* aes_buf,
+             int aes_buf_len)
+{
+  char *ptr;
+  uint32_t *len;
+  
+  *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
+  ptr = *result;
+  len = (uint32_t*) ptr;
+  *len = htonl (file_len);
+  ptr += 4;
+  len = (uint32_t*) ptr;
+  *len = htonl (aes_buf_len);
+  ptr += 4;
+  memcpy (ptr, aes_buf, aes_buf_len);
+  ptr += aes_buf_len;
+  len = (uint32_t*) ptr;
+  *len = htonl (cph_buf_len);
+  ptr += 4;
+  memcpy (ptr, cph_buf, cph_buf_len);
+  return 12 + cph_buf_len + aes_buf_len;
+}
+
+ssize_t
+read_cpabe (const void *data,
+            char** cph_buf,
+            int *cph_buf_len,
+            char** aes_buf,
+            int *aes_buf_len)
+{
+  int buf_len;
+  char *ptr;
+  uint32_t *len;
+
+  ptr = (char*)data;
+  len = (uint32_t*)ptr;
+  buf_len = ntohl (*len);
+  ptr += 4;
+  len = (uint32_t*)ptr;
+  *aes_buf_len = ntohl (*len);
+  ptr += 4;
+  *aes_buf = GNUNET_malloc (*aes_buf_len);
+  memcpy(*aes_buf, ptr, *aes_buf_len);
+  ptr += *aes_buf_len;
+  len = (uint32_t*)ptr;
+  *cph_buf_len = ntohl (*len);
+  ptr += 4;
+  *cph_buf = GNUNET_malloc (*cph_buf_len);
+  memcpy(*cph_buf, ptr, *cph_buf_len);
+
+  return buf_len;
+}
+
+ssize_t
+GNUNET_CRYPTO_cpabe_encrypt (const void *block,
+                             size_t size,
+                             const char *policy,
+                             const struct GNUNET_CRYPTO_AbeMasterKey *key,
+                             void **result)
+{
+  gabe_cph_t* cph;
+  char* plt;
+  char* cph_buf;
+  char* aes_buf;
+  element_t m;
+  int cph_buf_len;
+  int aes_buf_len;
+  ssize_t result_len;
+
+  if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
+    return GNUNET_SYSERR;
+  cph_buf_len = gabe_cph_serialize(cph,
+                                &cph_buf);
+  gabe_cph_free(cph);
+  GNUNET_free (cph);
+  plt = GNUNET_memdup (block, size);
+  aes_buf_len = aes_128_cbc_encrypt(plt, size, m, &aes_buf);
+  GNUNET_free (plt);
+  element_clear(m);
+  result_len = write_cpabe(result, size, cph_buf, cph_buf_len, aes_buf, 
aes_buf_len);
+  GNUNET_free(cph_buf);
+  GNUNET_free(aes_buf);
+  return result_len;
+}
+
+ssize_t
+GNUNET_CRYPTO_cpabe_decrypt (const void *block,
+                             size_t size,
+                             const struct GNUNET_CRYPTO_AbeKey *key,
+                             void **result)
+{
+  char* aes_buf;
+  char* cph_buf;
+  gabe_cph_t* cph;
+  element_t m;
+  int cph_buf_size;
+  int aes_buf_size;
+  int plt_len;
+
+  read_cpabe(block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
+  cph = gabe_cph_unserialize(key->pub, cph_buf, cph_buf_size);
+  if( !gabe_dec(key->pub, key->prv, cph, m) ) {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "%s\n", gabe_error());
+    GNUNET_free (aes_buf);
+    GNUNET_free (cph_buf);
+    gabe_cph_free(cph);
+    GNUNET_free (cph);
+    element_clear (m);
+    return GNUNET_SYSERR;
+  }
+  gabe_cph_free(cph);
+  GNUNET_free (cph);
+  plt_len = aes_128_cbc_decrypt(aes_buf, aes_buf_size, m, (char**)result);
+  GNUNET_free (cph_buf);
+  GNUNET_free (aes_buf);
+  element_clear (m);
+  //freeing is buggy in gabe
+  //gabe_prv_free (prv);
+  //gabe_pub_free (pub);
+  return plt_len;
+}
+
+ssize_t
+GNUNET_CRYPTO_cpabe_serialize_key (const struct GNUNET_CRYPTO_AbeKey *key,
+                                   void **result)
+{
+  ssize_t len;
+  char *pub;
+  char *prv;
+  int pub_len;
+  int prv_len;
+
+  pub_len = gabe_pub_serialize (key->pub, &pub);
+  prv_len = gabe_prv_serialize (key->prv, &prv);
+
+  len = pub_len + prv_len + 12;
+  write_cpabe (result, len, pub, pub_len, prv, prv_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (prv);
+
+  return len;
+}
+
+struct GNUNET_CRYPTO_AbeKey*
+GNUNET_CRYPTO_cpabe_deserialize_key (const void *data,
+                                     size_t len)
+{
+  struct GNUNET_CRYPTO_AbeKey *key;
+  char *pub;
+  char *prv;
+  int prv_len;
+  int pub_len;
+
+  key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
+  read_cpabe (data,
+              &pub,
+              &pub_len,
+              &prv,
+              &prv_len);
+  key->pub = gabe_pub_unserialize (pub, pub_len);
+  key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
+  
+  GNUNET_free (pub);
+  GNUNET_free (prv);
+  return key;
+}
+
+ssize_t
+GNUNET_CRYPTO_cpabe_serialize_master_key (const struct 
GNUNET_CRYPTO_AbeMasterKey *key,
+                                          void **result)
+{
+  ssize_t len;
+  char *pub;
+  char *msk;
+  int pub_len;
+  int msk_len;
+
+  pub_len = gabe_pub_serialize (key->pub, &pub);
+  msk_len = gabe_msk_serialize (key->msk, &msk);
+
+  len = pub_len + msk_len + 12;
+  write_cpabe (result, len, pub, pub_len, msk, msk_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (msk);
+
+  return len;
+}
+
+struct GNUNET_CRYPTO_AbeMasterKey*
+GNUNET_CRYPTO_cpabe_deserialize_master_key (const void *data,
+                                            size_t len)
+{
+  struct GNUNET_CRYPTO_AbeMasterKey *key;
+  char *msk;
+  char *pub;
+  int msk_len;
+  int pub_len;
+
+  key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
+  read_cpabe (data,
+              &pub,
+              &pub_len,
+              &msk,
+              &msk_len);
+  key->pub = gabe_pub_unserialize (pub, pub_len);
+  key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
+  
+  GNUNET_free (pub);
+  GNUNET_free (msk);
+
+  return key;
+}

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]