From: Schanzenbach, Martin Date: Mon, 4 Dec 2017 16:39:36 +0000 (+0100) Subject: -start jwt X-Git-Tag: gnunet-0.11.0rc0~24^2~8 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=24a0b84d503375bf66b5df932cd18631cc88cf8d;p=oweals%2Fgnunet.git -start jwt --- diff --git a/src/identity-attribute/Makefile.am b/src/identity-attribute/Makefile.am index 583545344..b84ad3492 100644 --- a/src/identity-attribute/Makefile.am +++ b/src/identity-attribute/Makefile.am @@ -20,7 +20,8 @@ lib_LTLIBRARIES = \ libgnunetidentityattribute.la libgnunetidentityattribute_la_SOURCES = \ - identity_attribute.c + identity_attribute.c \ + jwt.c libgnunetidentityattribute_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) diff --git a/src/identity-attribute/jwt.c b/src/identity-attribute/jwt.c new file mode 100644 index 000000000..935e0a79d --- /dev/null +++ b/src/identity-attribute/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 + + +#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* +GNUNET_IDENTITY_ATTRIBUTE_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-provider/jwt.c b/src/identity-provider/jwt.c deleted file mode 100644 index c8bc67806..000000000 --- a/src/identity-provider/jwt.c +++ /dev/null @@ -1,172 +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/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 "identity_attribute.h" -#include - - -#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 a ticket and attributes - * - * @param ticket the ticket - * @param attrs the attribute list - * @return a new base64-encoded JWT string. - */ -char* -jwt_create (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, - const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key) -{ - struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le; - 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; - json_t* body; - - /* TODO maybe we should use a local identity here */ - issuer = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - audience = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience, - 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 - */ - json_object_set_new (body, - le->attribute->name, - json_string (le->attribute->data)); - } - 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/include/gnunet_identity_attribute_lib.h b/src/include/gnunet_identity_attribute_lib.h index a43b509da..4c765515b 100644 --- a/src/include/gnunet_identity_attribute_lib.h +++ b/src/include/gnunet_identity_attribute_lib.h @@ -260,6 +260,20 @@ GNUNET_IDENTITY_ATTRIBUTE_value_to_string (uint32_t type, const char* GNUNET_IDENTITY_ATTRIBUTE_number_to_typename (uint32_t type); + +/** + * 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* +GNUNET_IDENTITY_ATTRIBUTE_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); + #if 0 /* keep Emacsens' auto-indent happy */ { #endif