aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/jwt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/jwt.c')
-rw-r--r--src/reclaim/jwt.c201
1 files changed, 0 insertions, 201 deletions
diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c
index 94db19b14..8b1378917 100644
--- a/src/reclaim/jwt.c
+++ b/src/reclaim/jwt.c
@@ -1,202 +1 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * @file reclaim/jwt.c
21 * @brief helper library for JSON-Web-Tokens
22 * @author Martin Schanzenbach
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_signatures.h"
27#include "gnunet_reclaim_attribute_lib.h"
28#include <jansson.h>
29
30
31#define JWT_ALG "alg"
32
33/* Use 512bit HMAC */
34#define JWT_ALG_VALUE "HS512"
35
36#define JWT_TYP "typ"
37
38#define JWT_TYP_VALUE "jwt"
39
40#define SERVER_ADDRESS "https://reclaim.id"
41
42static char*
43create_jwt_header(void)
44{
45 json_t *root;
46 char *json_str;
47
48 root = json_object ();
49 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
50 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
51
52 json_str = json_dumps (root, JSON_INDENT(0) | JSON_COMPACT);
53 json_decref (root);
54 return json_str;
55}
56
57static void
58replace_char(char* str, char find, char replace){
59 char *current_pos = strchr(str,find);
60 while (current_pos){
61 *current_pos = replace;
62 current_pos = strchr(current_pos,find);
63 }
64}
65
66//RFC4648
67static void
68fix_base64(char* str) {
69 char *padding;
70 //First, remove trailing padding '='
71 padding = strtok(str, "=");
72 while (NULL != padding)
73 padding = strtok(NULL, "=");
74
75 //Replace + with -
76 replace_char (str, '+', '-');
77
78 //Replace / with _
79 replace_char (str, '/', '_');
80
81}
82
83/**
84 * Create a JWT from attributes
85 *
86 * @param aud_key the public of the audience
87 * @param sub_key the public key of the subject
88 * @param attrs the attribute list
89 * @param expiration_time the validity of the token
90 * @param secret_key the key used to sign the JWT
91 * @return a new base64-encoded JWT string.
92 */
93char*
94jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
95 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
96 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
97 const struct GNUNET_TIME_Relative *expiration_time,
98 const char *nonce,
99 const char *secret_key)
100{
101 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
102 struct GNUNET_HashCode signature;
103 struct GNUNET_TIME_Absolute exp_time;
104 struct GNUNET_TIME_Absolute time_now;
105 char* audience;
106 char* subject;
107 char* header;
108 char* body_str;
109 char* result;
110 char* header_base64;
111 char* body_base64;
112 char* signature_target;
113 char* signature_base64;
114 char* attr_val_str;
115 json_t* body;
116
117 //iat REQUIRED time now
118 time_now = GNUNET_TIME_absolute_get();
119 //exp REQUIRED time expired from config
120 exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
121 //auth_time only if max_age
122 //nonce only if nonce
123 // OPTIONAL acr,amr,azp
124 subject = GNUNET_STRINGS_data_to_string_alloc (sub_key,
125 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
126 audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
127 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
128 header = create_jwt_header ();
129 body = json_object ();
130
131 //iss REQUIRED case sensitive server uri with https
132 //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid)
133 json_object_set_new (body,
134 "iss", json_string (SERVER_ADDRESS));
135 //sub REQUIRED public key identity, not exceed 255 ASCII length
136 json_object_set_new (body,
137 "sub", json_string (subject));
138 //aud REQUIRED public key client_id must be there
139 json_object_set_new (body,
140 "aud", json_string (audience));
141 //iat
142 json_object_set_new (body,
143 "iat", json_integer (time_now.abs_value_us / (1000*1000)));
144 //exp
145 json_object_set_new (body,
146 "exp", json_integer (exp_time.abs_value_us / (1000*1000)));
147 //nbf
148 json_object_set_new (body,
149 "nbf", json_integer (time_now.abs_value_us / (1000*1000)));
150 //nonce
151 if (NULL != nonce)
152 json_object_set_new (body,
153 "nonce", json_string (nonce));
154
155 for (le = attrs->list_head; NULL != le; le = le->next)
156 {
157 attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
158 le->claim->data,
159 le->claim->data_size);
160 json_object_set_new (body,
161 le->claim->name,
162 json_string (attr_val_str));
163 GNUNET_free (attr_val_str);
164 }
165 body_str = json_dumps (body, JSON_INDENT(0) | JSON_COMPACT);
166 json_decref (body);
167
168 GNUNET_STRINGS_base64_encode (header,
169 strlen (header),
170 &header_base64);
171 fix_base64(header_base64);
172
173 GNUNET_STRINGS_base64_encode (body_str,
174 strlen (body_str),
175 &body_base64);
176 fix_base64(body_base64);
177
178 GNUNET_free (subject);
179 GNUNET_free (audience);
180
181 /**
182 * Creating the JWT signature. This might not be
183 * standards compliant, check.
184 */
185 GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
186 GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, strlen (signature_target), &signature);
187 GNUNET_STRINGS_base64_encode ((const char*)&signature,
188 sizeof (struct GNUNET_HashCode),
189 &signature_base64);
190 fix_base64(signature_base64);
191
192 GNUNET_asprintf (&result, "%s.%s.%s",
193 header_base64, body_base64, signature_base64);
194
195 GNUNET_free (signature_target);
196 GNUNET_free (header);
197 GNUNET_free (body_str);
198 GNUNET_free (signature_base64);
199 GNUNET_free (body_base64);
200 GNUNET_free (header_base64);
201 return result;
202}