aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-08-31 17:59:47 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2022-08-31 17:59:47 +0200
commit4a2c758df3b20104580fc5ff9efc1d6cd7237bd0 (patch)
tree122fac6e24f9c8f5bbdc2824d06a6166f976033a /src/reclaim
parentcc70504a2f2756107976924843fe6b39b9ac94cb (diff)
parent6f72f195810305071da63061a84fed035d7368d6 (diff)
downloadgnunet-4a2c758df3b20104580fc5ff9efc1d6cd7237bd0.tar.gz
gnunet-4a2c758df3b20104580fc5ff9efc1d6cd7237bd0.zip
-fixup merge
Diffstat (limited to 'src/reclaim')
-rw-r--r--src/reclaim/.gitignore2
-rw-r--r--src/reclaim/Makefile.am44
-rw-r--r--src/reclaim/did_core.c267
-rw-r--r--src/reclaim/did_core.h138
-rw-r--r--src/reclaim/did_helper.c203
-rw-r--r--src/reclaim/did_helper.h74
-rw-r--r--src/reclaim/gnunet-did.c482
-rw-r--r--src/reclaim/test_did_helper.c131
8 files changed, 973 insertions, 368 deletions
diff --git a/src/reclaim/.gitignore b/src/reclaim/.gitignore
index ac76b6b2f..e22aa5011 100644
--- a/src/reclaim/.gitignore
+++ b/src/reclaim/.gitignore
@@ -1,3 +1,5 @@
1gnunet-reclaim 1gnunet-reclaim
2gnunet-service-reclaim 2gnunet-service-reclaim
3gnunet-did 3gnunet-did
4test_did_helper
5test_reclaim_attribute
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
index 2f3df3456..d29b5857a 100644
--- a/src/reclaim/Makefile.am
+++ b/src/reclaim/Makefile.am
@@ -38,7 +38,8 @@ pkgcfg_DATA = \
38 reclaim.conf 38 reclaim.conf
39 39
40lib_LTLIBRARIES = \ 40lib_LTLIBRARIES = \
41 libgnunetreclaim.la 41 libgnunetreclaim.la \
42 libgnunetdid.la
42plugin_LTLIBRARIES = \ 43plugin_LTLIBRARIES = \
43 libgnunet_plugin_gnsrecord_reclaim.la \ 44 libgnunet_plugin_gnsrecord_reclaim.la \
44 libgnunet_plugin_reclaim_attribute_basic.la \ 45 libgnunet_plugin_reclaim_attribute_basic.la \
@@ -142,6 +143,22 @@ libgnunetreclaim_la_LDFLAGS = \
142 $(GN_LIB_LDFLAGS) \ 143 $(GN_LIB_LDFLAGS) \
143 -version-info 0:0:0 144 -version-info 0:0:0
144 145
146libgnunetdid_la_SOURCES = \
147 did_helper.c \
148 did_helper.h \
149 did_core.h \
150 did_core.c
151libgnunetdid_la_LIBADD = \
152 $(top_builddir)/src/util/libgnunetutil.la \
153 $(top_builddir)/src/gns/libgnunetgns.la \
154 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
155 $(top_builddir)/src/identity/libgnunetidentity.la \
156 $(top_builddir)/src/namestore/libgnunetnamestore.la \
157 -ljansson \
158 $(GN_LIBINTL) $(XLIB)
159libgnunetdid_la_LDFLAGS = \
160 $(GN_LIB_LDFLAGS) \
161 -version-info 0:0:0
145 162
146libgnunet_plugin_reclaim_attribute_basic_la_SOURCES = \ 163libgnunet_plugin_reclaim_attribute_basic_la_SOURCES = \
147 plugin_reclaim_attribute_basic.c 164 plugin_reclaim_attribute_basic.c
@@ -194,22 +211,27 @@ test_reclaim_attribute_LDADD = \
194 $(GN_LIBINTL) 211 $(GN_LIBINTL)
195 212
196gnunet_did_SOURCES = \ 213gnunet_did_SOURCES = \
197 gnunet-did.c \ 214 gnunet-did.c
198 did_misc.c \
199 did.h
200gnunet_did_LDADD = \ 215gnunet_did_LDADD = \
201 $(top_builddir)/src/util/libgnunetutil.la \ 216 $(top_builddir)/src/util/libgnunetutil.la \
202 $(top_builddir)/src/gns/libgnunetgns.la \ 217 $(top_builddir)/src/gns/libgnunetgns.la \
203 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 218 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
204 $(top_builddir)/src/identity/libgnunetidentity.la \ 219 $(top_builddir)/src/identity/libgnunetidentity.la \
205 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 220 $(top_builddir)/src/namestore/libgnunetnamestore.la \
221 libgnunetdid.la \
206 -ljansson 222 -ljansson
207 223
208 224
209test_w3c_ed25519_2020_SOURCES = \ 225test_did_helper_SOURCES = \
210 test_w3c_ed25519_2020.c 226 test_did_helper.c
211test_w3c_ed25519_2020_LDADD = \ 227test_did_helper_LDADD = \
212 $(top_builddir)/src/util/libgnunetutil.la 228 $(top_builddir)/src/util/libgnunetutil.la \
229 $(top_builddir)/src/gns/libgnunetgns.la \
230 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
231 $(top_builddir)/src/identity/libgnunetidentity.la \
232 $(top_builddir)/src/namestore/libgnunetnamestore.la \
233 libgnunetdid.la \
234 -ljansson
213 235
214check_SCRIPTS = \ 236check_SCRIPTS = \
215 test_reclaim_attribute.sh \ 237 test_reclaim_attribute.sh \
@@ -218,9 +240,11 @@ check_SCRIPTS = \
218 240
219check_PROGRAMS = \ 241check_PROGRAMS = \
220 test_reclaim_attribute \ 242 test_reclaim_attribute \
221 test_w3c_ed25519_2020 243 test_did_helper
222 244
223if ENABLE_TEST_RUN 245if ENABLE_TEST_RUN
224 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 246 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
225 TESTS = $(check_SCRIPTS) 247 TESTS = \
248 $(check_SCRIPTS) \
249 $(check_PROGRAMS)
226endif 250endif
diff --git a/src/reclaim/did_core.c b/src/reclaim/did_core.c
new file mode 100644
index 000000000..949ed6a69
--- /dev/null
+++ b/src/reclaim/did_core.c
@@ -0,0 +1,267 @@
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/did_core.c
23 * @brief Core functionality for DID
24 * @author Tristan Schwieren
25 */
26
27// TODO: DID documents do not have an expiration date. Still we add one
28// TODO: Store DID document with empty label and own type (maybe DID-Document or JSON??)
29
30#include "did_core.h"
31
32struct DID_resolve_return
33{
34 DID_resolve_callback *cb;
35 void *cls;
36};
37
38struct DID_action_return
39{
40 DID_action_callback *cb;
41 void *cls;
42};
43
44// ------------------------------------------------ //
45// -------------------- Resolve ------------------- //
46// ------------------------------------------------ //
47
48/**
49 * @brief GNS lookup callback. Calls the given callback function
50 * and gives it the DID Document.
51 * Fails if there is more than one DID record.
52 *
53 * @param cls closure
54 * @param rd_count number of records in rd
55 * @param rd the records in the reply
56 */
57static void
58DID_resolve_gns_lookup_cb (
59 void *cls,
60 uint32_t rd_count,
61 const struct GNUNET_GNSRECORD_Data *rd)
62{
63 char *did_document;
64 DID_resolve_callback *cb = ((struct DID_resolve_return *) cls)->cb;
65 void *cls_did_resolve_cb = ((struct DID_resolve_return *) cls)->cls;
66 free (cls);
67
68 if (rd_count != 1)
69 cb (GNUNET_NO, "An ego should only have one DID Document",
70 cls_did_resolve_cb);
71
72 if (rd[0].record_type == GNUNET_DNSPARSER_TYPE_TXT)
73 {
74 did_document = (char *) rd[0].data;
75 cb (GNUNET_OK, did_document, cls_did_resolve_cb);
76 }
77 else
78 cb (GNUNET_NO, "DID Document is not a TXT record\n", cls_did_resolve_cb);
79}
80
81/**
82 * @brief Resolve a DID.
83 * Calls the given callback function with the resolved DID Document and the given closure.
84 * If the did can not be resolved did_document is NULL.
85 *
86 * @param did DID that is resolve
87 */
88enum GNUNET_GenericReturnValue
89DID_resolve (const char *did,
90 struct GNUNET_GNS_Handle *gns_handle,
91 DID_resolve_callback *cont,
92 void *cls)
93{
94 struct GNUNET_IDENTITY_PublicKey pkey;
95
96 // did, gns_handle and cont must me set
97 if ((did == NULL) || (gns_handle == NULL) || (cont == NULL))
98 return GNUNET_NO;
99
100 if (GNUNET_OK != DID_did_to_pkey (did, &pkey))
101 return GNUNET_NO;
102
103 // Create closure for lookup callback
104 struct DID_resolve_return *cls_gns_lookup_cb
105 = malloc (sizeof(struct DID_resolve_return));
106 cls_gns_lookup_cb->cb = cont;
107 cls_gns_lookup_cb->cls = cls;
108
109 GNUNET_GNS_lookup (gns_handle,
110 DID_DOCUMENT_LABEL,
111 &pkey,
112 GNUNET_DNSPARSER_TYPE_TXT,
113 GNUNET_GNS_LO_DEFAULT,
114 &DID_resolve_gns_lookup_cb,
115 cls_gns_lookup_cb);
116
117 return GNUNET_OK;
118}
119
120// ------------------------------------------------ //
121// -------------------- Create -------------------- //
122// ------------------------------------------------ //
123
124static void
125DID_create_did_store_cb (void *cls,
126 int32_t success,
127 const char *emsg)
128{
129 DID_action_callback *cb = ((struct DID_action_return *) cls)->cb;
130 void *cls_did_create_cb = ((struct DID_action_return *) cls)->cls;
131 free (cls);
132
133 if (GNUNET_OK == success)
134 {
135 cb (GNUNET_OK, (void *) cls_did_create_cb);
136 }
137 else
138 {
139 // TODO: Log emsg. Not writing it to STDOUT
140 printf ("%s\n", emsg);
141 cb (GNUNET_NO, (void *) cls_did_create_cb);
142 }
143}
144
145struct DID_create_namestore_lookup_closure
146{
147 const char *did_document;
148 struct GNUNET_TIME_Relative expire_time;
149 struct GNUNET_NAMESTORE_Handle *namestore_handle;
150 struct DID_action_return *ret;
151};
152
153static void
154DID_create_namestore_lookup_cb (void *cls,
155 const struct
156 GNUNET_IDENTITY_PrivateKey *zone,
157 const char *label,
158 unsigned int rd_count,
159 const struct GNUNET_GNSRECORD_Data *rd)
160{
161 struct GNUNET_GNSRECORD_Data record_data;
162 struct GNUNET_IDENTITY_PublicKey pkey;
163
164 const char *did_document
165 = ((struct DID_create_namestore_lookup_closure *) cls)->did_document;
166
167 const struct GNUNET_TIME_Relative expire_time
168 = ((struct DID_create_namestore_lookup_closure *) cls)->expire_time;
169
170 struct GNUNET_NAMESTORE_Handle *namestore_handle
171 = ((struct DID_create_namestore_lookup_closure *) cls)->namestore_handle;
172
173 struct DID_action_return *cls_record_store_cb
174 = ((struct DID_create_namestore_lookup_closure *) cls)->ret;
175
176 free (cls);
177
178 if (rd_count > 0)
179 {
180 printf ("Ego already has a DID Document. Abort.\n");
181 cls_record_store_cb->cb (GNUNET_NO, cls_record_store_cb->cls);
182 }
183 else {
184 // Get public key
185 GNUNET_IDENTITY_key_get_public (zone, &pkey);
186
187 // If no DID Document is given a default one is created
188 if (did_document != NULL)
189 printf (
190 "DID Docuement is read from \"DID-document\" argument (EXPERIMENTAL)\n");
191 else
192 did_document = DID_pkey_to_did_document (&pkey);
193
194 // Create record
195 record_data.data = did_document;
196 record_data.expiration_time = expire_time.rel_value_us;
197 record_data.data_size = strlen (did_document) + 1;
198 record_data.record_type = GNUNET_GNSRECORD_typename_to_number ("TXT"),
199 record_data.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
200
201 // Store record
202 GNUNET_NAMESTORE_records_store (namestore_handle,
203 zone,
204 DID_DOCUMENT_LABEL,
205 1, // FIXME what if GNUNET_GNS_EMPTY_LABEL_AT has records
206 &record_data,
207 &DID_create_did_store_cb,
208 (void *) cls_record_store_cb);
209 }
210}
211
212/**
213 * @brief Creates a DID and saves DID Document in Namestore.
214 *
215 * @param ego ego for which the DID should be created.
216 * @param did_document did_document that should be saved in namestore.
217 * If did_document==NULL -> Default DID document is created.
218 * @param namestore_handle
219 * @param cont callback function
220 * @param cls closure
221 */
222enum GNUNET_GenericReturnValue
223DID_create (const struct GNUNET_IDENTITY_Ego *ego,
224 const char *did_document,
225 const struct GNUNET_TIME_Relative *expire_time,
226 struct GNUNET_NAMESTORE_Handle *namestore_handle,
227 DID_action_callback *cont,
228 void *cls)
229{
230 struct GNUNET_IDENTITY_PublicKey pkey;
231
232 // Ego, namestore_handle and cont must be set
233 if ((ego == NULL) || (namestore_handle == NULL) || (cont == NULL))
234 return GNUNET_NO;
235
236 // Check if ego has EdDSA key
237 GNUNET_IDENTITY_ego_get_public_key ((struct GNUNET_IDENTITY_Ego *) ego,
238 &pkey);
239 if (ntohl (pkey.type) != GNUNET_GNSRECORD_TYPE_EDKEY)
240 {
241 printf ("The EGO has to have an EdDSA key pair\n");
242 return GNUNET_NO;
243 }
244
245 struct DID_action_return *ret
246 = malloc (sizeof(struct DID_action_return));
247 ret->cb = cont;
248 ret->cls = cls;
249
250 struct DID_create_namestore_lookup_closure *cls_name_store_lookup_cb
251 = malloc (sizeof(struct DID_create_namestore_lookup_closure));
252 cls_name_store_lookup_cb->did_document = did_document;
253 cls_name_store_lookup_cb->expire_time = (*expire_time);
254 cls_name_store_lookup_cb->namestore_handle = namestore_handle;
255 cls_name_store_lookup_cb->ret = ret;
256
257 // Check if ego already has a DID Document
258 GNUNET_NAMESTORE_records_lookup (namestore_handle,
259 GNUNET_IDENTITY_ego_get_private_key (ego),
260 DID_DOCUMENT_LABEL,
261 NULL,
262 NULL,
263 DID_create_namestore_lookup_cb,
264 (void *) cls_name_store_lookup_cb);
265
266 return GNUNET_OK;
267}
diff --git a/src/reclaim/did_core.h b/src/reclaim/did_core.h
new file mode 100644
index 000000000..842424e14
--- /dev/null
+++ b/src/reclaim/did_core.h
@@ -0,0 +1,138 @@
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/did_core.h
23 * @brief Core functionality for GNUNET Decentralized Identifier
24 * @author Tristan Schwieren
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gns_service.h"
31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_identity_service.h"
33#include "did_helper.h"
34#include "jansson.h"
35
36// #define DID_DOCUMENT_LABEL GNUNET_GNS_EMPTY_LABEL_AT
37#define DID_DOCUMENT_LABEL "didd"
38#define DID_DOCUMENT_DEFAULT_EXPIRATION_TIME "365d"
39
40/**
41 * @brief Signature of a callback function that is called after a did has been resolved.
42 * did_document contains an Error message if DID can not be resolved.
43 * Calls the given callback function with the resolved DID Document and the given closure.
44 * If the did can not be resolved did_document is NULL.
45 * @param status Equals GNUNET_OK if DID Docuemnt has been resolved
46 * @param did_document resolved DID Document
47 * @param cls previsouly given closure
48 */
49typedef void
50 DID_resolve_callback (enum GNUNET_GenericReturnValue status, char *did_document, void *cls);
51
52/**
53 * @brief Signature of a callback function that is called after a did has been removed
54 * status = 0 if action was sucessfull
55 * status = 1 if action failed
56 *
57 * @param status status of the perfermormed action.
58 * @param cls previsouly given closure
59 */
60typedef void
61 DID_action_callback (enum GNUNET_GenericReturnValue status, void *cls);
62
63
64/**
65 * @brief Resolve a DID.
66 * Calls the given callback function with the resolved DID Document and the given closure.
67 * If the did can not be resolved did_document is NULL.
68 *
69 * @param did DID that is resolved
70 * @param gns_handle pointer to gns handle.
71 * @param cont callback function
72 * @param cls closure
73 */
74enum GNUNET_GenericReturnValue
75DID_resolve (const char *did,
76 struct GNUNET_GNS_Handle *gns_handle,
77 DID_resolve_callback *cont,
78 void *cls);
79
80
81/**
82 * @brief Removes the DID Document from namestore.
83 * Ego is not removed.
84 * Calls the callback function with status and the given closure.
85 *
86 * @param ego ego which controlls the DID
87 * @param cfg_handle pointer to configuration handle
88 * @param namestore_handle pointer to namestore handle
89 * @param cont callback function
90 * @param cls closure
91 */
92enum GNUNET_GenericReturnValue
93DID_remove (const struct GNUNET_IDENTITY_Ego *ego,
94 struct GNUNET_CONFIGURATION_Handle *cfg_handle,
95 struct GNUNET_NAMESTORE_Handle *namestore_handle,
96 DID_action_callback *cont,
97 void *cls);
98
99
100/**
101 * @brief Creates a DID and saves DID Document in Namestore.
102 *
103 * @param ego ego for which the DID should be created.
104 * @param did_document did_document that should be saved in namestore.
105 * If did_document==NULL -> Default DID document is created.
106 * @param expire_time
107 * @param namestore_handle
108 * @param cont callback function
109 * @param cls closure
110 */
111enum GNUNET_GenericReturnValue
112DID_create (const struct GNUNET_IDENTITY_Ego *ego,
113 const char *did_document,
114 const struct GNUNET_TIME_Relative *expire_time,
115 struct GNUNET_NAMESTORE_Handle *namestore_handle,
116 DID_action_callback *cont,
117 void *cls);
118
119
120/**
121 * @brief Replace the DID Document of a DID.
122 *
123 * @param ego ego for which the DID Document should be replaced
124 * @param did_document new DID Document
125 * @param cfg_handle pointer to configuration handle
126 * @param identity_handle pointer to configuration handle
127 * @param namestore_handle pointer to namestore handle
128 * @param cont callback function
129 * @param cls closure
130 */
131enum GNUNET_GenericReturnValue
132DID_replace (struct GNUNET_IDENTITY_Ego *ego,
133 char *did_document,
134 const struct GNUNET_CONFIGURATION_Handle *cfg_handle,
135 struct GNUNET_IDENTITY_Handle *identity_handle,
136 struct GNUNET_NAMESTORE_Handle *namestore_handle,
137 DID_action_callback *cont,
138 void *cls);
diff --git a/src/reclaim/did_helper.c b/src/reclaim/did_helper.c
new file mode 100644
index 000000000..1c04ede33
--- /dev/null
+++ b/src/reclaim/did_helper.c
@@ -0,0 +1,203 @@
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/did_helper.c
23 * @brief helper library for DID related functions
24 * @author Tristan Schwieren
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_namestore_service.h"
29#include "gnunet_gns_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "did_helper.h"
32#include "jansson.h"
33
34#define STR_INDIR(x) #x
35#define STR(x) STR_INDIR (x)
36
37/**
38 * @brief Generate a DID for a given GNUNET public key
39 *
40 * @param pkey
41 * @return char* Returns the DID. Caller must free
42 * TODO: Check if EdDSA
43 */
44char*
45DID_pkey_to_did (struct GNUNET_IDENTITY_PublicKey *pkey)
46{
47 char *pkey_str;
48 char *did_str;
49
50 pkey_str = GNUNET_IDENTITY_public_key_to_string (pkey);
51 GNUNET_asprintf (&did_str, "%s%s",
52 GNUNET_DID_METHOD_PREFIX,
53 pkey_str);
54
55 GNUNET_free (pkey_str);
56 return did_str;
57}
58
59/**
60 * @brief Generate a DID for a given gnunet EGO.
61 * Wrapper around GNUNET_DID_pkey_to_did
62 *
63 * @param ego
64 * @return char* Returns the DID. Caller must free
65 */
66char*
67DID_identity_to_did (struct GNUNET_IDENTITY_Ego *ego)
68{
69 struct GNUNET_IDENTITY_PublicKey pkey;
70
71 GNUNET_IDENTITY_ego_get_public_key (ego, &pkey);
72 return DID_pkey_to_did (&pkey);
73}
74
75/**
76 * @brief Return the public key of a DID
77 */
78enum GNUNET_GenericReturnValue
79DID_did_to_pkey (const char *did, struct GNUNET_IDENTITY_PublicKey *pkey)
80{
81 char pkey_str[MAX_DID_SPECIFIC_IDENTIFIER_LENGTH];
82
83 if ((1 != (sscanf (did,
84 GNUNET_DID_METHOD_PREFIX "%"
85 STR (MAX_DID_SPECIFIC_IDENTIFIER_LENGTH)
86 "s", pkey_str))) ||
87 (GNUNET_OK != GNUNET_IDENTITY_public_key_from_string (pkey_str, pkey)))
88 {
89 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not decode given DID: %s\n",
90 did);
91 return GNUNET_NO;
92 }
93
94 return GNUNET_OK;
95}
96
97/**
98 * @brief Convert a base 64 encoded public key to a GNUNET key
99 */
100struct GNUNET_IDENTITY_PublicKey *
101GNUNET_DID_key_covert_multibase_base64_to_gnunet (char *pkey_str)
102{
103 return NULL;
104}
105
106/**
107 * @brief Convert GNUNET key to a base 64 encoded public key
108 */
109char *
110DID_key_covert_gnunet_to_multibase_base64 (struct
111 GNUNET_IDENTITY_PublicKey *
112 pkey)
113{
114 struct GNUNET_CRYPTO_EddsaPublicKey pubkey = pkey->eddsa_key;
115
116 // This is how to convert out pubkeys to W3c Ed25519-2020 multibase (base64url no padding)
117 char *pkey_base_64;
118 char *pkey_multibase;
119 char pkx[34];
120
121 pkx[0] = 0xed;
122 pkx[1] = 0x01;
123 memcpy (pkx + 2, &pubkey, sizeof (pubkey));
124 GNUNET_STRINGS_base64url_encode (pkx, sizeof (pkx), &pkey_base_64);
125 GNUNET_asprintf (&pkey_multibase, "u%s", pkey_base_64);
126
127 GNUNET_free (pkey_base_64);
128 return pkey_multibase;
129}
130
131/**
132 * @brief Create a did generate did object
133 *
134 * @param pkey
135 * @return void* Return pointer to the DID Document
136 */
137char *
138DID_pkey_to_did_document (struct GNUNET_IDENTITY_PublicKey *pkey)
139{
140
141 /* FIXME-MSC: This is effectively creating a DID Document default template for
142 * the initial document.
143 * Maybe this can be refactored to generate such a template for an identity?
144 * Even if higher layers add/modify it, there should probably still be a
145 * GNUNET_DID_document_template_from_identity()
146 */
147
148 char *did_str;
149 char *verify_id_str;
150 char *pkey_multibase_str;
151 char *didd_str;
152 json_t *didd_json;
153
154 did_str = DID_pkey_to_did (pkey);
155 GNUNET_asprintf (&verify_id_str, "%s#key-1", did_str);
156
157 pkey_multibase_str = DID_key_covert_gnunet_to_multibase_base64 (pkey);
158
159 didd_json = json_pack (
160 "{s:[ss], s:s, s:[{s:s, s:s, s:s, s:s}], s:[s], s:[s]}",
161 "@context",
162 "https://www.w3.org/ns/did/v1",
163 "https://w3id.org/security/suites/ed25519-2020/v1",
164 "id",
165 did_str,
166 "verificationMethod",
167 "id",
168 verify_id_str,
169 "type",
170 "Ed25519VerificationKey2020",
171 "controller",
172 did_str,
173 "publicKeyMultibase",
174 pkey_multibase_str,
175 "authentication",
176 "#key-1",
177 "assertionMethod",
178 "#key-1");
179
180 // Encode DID Document as JSON string
181 didd_str = json_dumps (didd_json, JSON_INDENT (2));
182
183 // Free
184 GNUNET_free (did_str);
185 GNUNET_free (verify_id_str);
186 GNUNET_free (pkey_multibase_str);
187 json_decref (didd_json);
188
189 return didd_str;
190}
191
192/**
193 * @brief Generate the default DID document for a GNUNET ego
194 * Wrapper around GNUNET_DID_pkey_to_did_document
195 */
196char *
197DID_identity_to_did_document (struct GNUNET_IDENTITY_Ego *ego)
198{
199 struct GNUNET_IDENTITY_PublicKey pkey;
200
201 GNUNET_IDENTITY_ego_get_public_key (ego, &pkey);
202 return DID_pkey_to_did (&pkey);
203} \ No newline at end of file
diff --git a/src/reclaim/did_helper.h b/src/reclaim/did_helper.h
new file mode 100644
index 000000000..c3ee457af
--- /dev/null
+++ b/src/reclaim/did_helper.h
@@ -0,0 +1,74 @@
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/did_helper.h
23 * @brief helper library for DID related functions
24 * @author Tristan Schwieren
25 */
26
27#define GNUNET_DID_METHOD_PREFIX "did:reclaim:"
28#define MAX_DID_SPECIFIC_IDENTIFIER_LENGTH 59
29
30/**
31 * @brief Return a DID for a given GNUNET public key
32 */
33char *
34DID_pkey_to_did (struct GNUNET_IDENTITY_PublicKey *pkey);
35
36/**
37 * @brief Generate a DID for a given gnunet EGO
38 *
39 * @param ego
40 * @return char * Returns the DID. Caller must free
41 */
42char *
43DID_identity_to_did (struct GNUNET_IDENTITY_Ego *ego);
44
45/**
46 * @brief Return the public key of a DID
47 */
48enum GNUNET_GenericReturnValue
49DID_did_to_pkey (const char *did, struct GNUNET_IDENTITY_PublicKey *pkey);
50
51// /**
52// * @brief Convert a base 64 encoded public key to a GNUNET key
53// */
54// struct GNUNET_IDENTITY_PublicKey *
55// GNUNET_DID_key_covert_multibase_base64_to_gnunet(char *);
56
57/**
58 * @brief Convert GNUNET key to a base 64 encoded public key
59 */
60char *
61DID_key_covert_gnunet_to_multibase_base64 (struct
62 GNUNET_IDENTITY_PublicKey *);
63
64/**
65 * @brief Generate the default DID document for a GNUNET public key
66 */
67char *
68DID_pkey_to_did_document (struct GNUNET_IDENTITY_PublicKey *pkey);
69
70/**
71 * @brief Generate the default DID document for a GNUNET ego
72 */
73char *
74DID_identity_to_did_document (struct GNUNET_IDENTITY_Ego *ego); \ No newline at end of file
diff --git a/src/reclaim/gnunet-did.c b/src/reclaim/gnunet-did.c
index 4c5704d44..6f802aded 100644
--- a/src/reclaim/gnunet-did.c
+++ b/src/reclaim/gnunet-did.c
@@ -36,10 +36,12 @@
36#include "platform.h" 36#include "platform.h"
37#include "gnunet_util_lib.h" 37#include "gnunet_util_lib.h"
38#include "gnunet_namestore_service.h" 38#include "gnunet_namestore_service.h"
39#include "gnunet_identity_service.h"
39#include "gnunet_gns_service.h" 40#include "gnunet_gns_service.h"
40#include "gnunet_gnsrecord_lib.h" 41#include "gnunet_gnsrecord_lib.h"
42#include "did_helper.h"
43#include "did_core.h"
41#include "jansson.h" 44#include "jansson.h"
42#include "did.h"
43 45
44#define GNUNET_DID_DEFAULT_DID_DOCUMENT_EXPIRATION_TIME "1d" 46#define GNUNET_DID_DEFAULT_DID_DOCUMENT_EXPIRATION_TIME "1d"
45 47
@@ -147,73 +149,6 @@ cleanup (void *cls)
147} 149}
148 150
149/** 151/**
150 * @brief Callback for ego loockup of get_did_for_ego()
151 *
152 * @param cls closure
153 * @param ego the returned ego
154 */
155static void
156get_did_for_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
157{
158 char *did_str;
159
160 if (ego == NULL)
161 {
162 printf ("EGO not found\n");
163 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
164 ret = 1;
165 return;
166 }
167 did_str = DID_ego_to_did (ego);
168
169 printf ("%s\n", did_str);
170
171 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
172 ret = 0;
173 return;
174}
175
176/**
177 * @brief Get the DID for a given EGO
178 *
179 */
180static void
181get_did_for_ego ()
182{
183 if (egoname != NULL)
184 {
185 GNUNET_IDENTITY_ego_lookup (my_cfg,
186 egoname,
187 &get_did_for_ego_lookup_cb,
188 NULL);
189 }
190 else {
191 printf ("Set the EGO argument to get the DID for a given EGO\n");
192 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
193 ret = 1;
194 return;
195 }
196}
197
198
199/**
200 * @brief Get the public key from did attribute given by the user
201 *
202 * @param pkey place to write the public key to
203 */
204static void
205get_pkey_from_attr_did (struct GNUNET_IDENTITY_PublicKey *pkey)
206{
207 if (GNUNET_OK != DID_public_key_from_did (did, pkey))
208 {
209 fprintf (stderr, _("Invalid DID `%s'\n"), did);
210 GNUNET_SCHEDULER_add_now (cleanup, NULL);
211 ret = 1;
212 return;
213 }
214}
215
216/**
217 * @brief GNS lookup callback. Prints the DID Document to standard out. 152 * @brief GNS lookup callback. Prints the DID Document to standard out.
218 * Fails if there is more than one DID record. 153 * Fails if there is more than one DID record.
219 * 154 *
@@ -223,32 +158,17 @@ get_pkey_from_attr_did (struct GNUNET_IDENTITY_PublicKey *pkey)
223 */ 158 */
224static void 159static void
225print_did_document ( 160print_did_document (
226 void *cls, 161 enum GNUNET_GenericReturnValue status,
227 uint32_t rd_count, 162 char *did_document,
228 const struct GNUNET_GNSRECORD_Data *rd) 163 void *cls
164 )
229{ 165{
230 /* 166 if (GNUNET_OK == status)
231 * FIXME-MSC: The user may decide to put other records here. 167 printf ("%s\n", did_document);
232 * In general I am fine with the constraint here, but not when 168 else
233 * we move it to "@" 169 printf ("An error occured: %s\n", did_document);
234 */
235 if (rd_count != 1)
236 {
237 printf ("An ego should only have one DID Document\n");
238 GNUNET_SCHEDULER_add_now (cleanup, NULL);
239 ret = 1;
240 return;
241 }
242
243 if (rd[0].record_type == GNUNET_DNSPARSER_TYPE_TXT)
244 {
245 printf ("%s\n", (char *) rd[0].data);
246 }
247 else {
248 printf ("DID Document is not a TXT record\n");
249 }
250 170
251 GNUNET_SCHEDULER_add_now (&cleanup, NULL); 171 GNUNET_SCHEDULER_add_now (cleanup, NULL);
252 ret = 0; 172 ret = 0;
253 return; 173 return;
254} 174}
@@ -257,7 +177,7 @@ print_did_document (
257 * @brief Resolve a DID given by the user. 177 * @brief Resolve a DID given by the user.
258 */ 178 */
259static void 179static void
260resolve_did_document () 180resolve_did ()
261{ 181{
262 struct GNUNET_IDENTITY_PublicKey pkey; 182 struct GNUNET_IDENTITY_PublicKey pkey;
263 183
@@ -269,10 +189,13 @@ resolve_did_document ()
269 return; 189 return;
270 } 190 }
271 191
272 get_pkey_from_attr_did (&pkey); 192 if (GNUNET_OK != DID_resolve (did, gns_handle, print_did_document, NULL))
273 193 {
274 GNUNET_GNS_lookup (gns_handle, GNUNET_GNS_EMPTY_LABEL_AT, &pkey, GNUNET_DNSPARSER_TYPE_TXT, 194 printf ("An error occured while resoling the DID\n");
275 GNUNET_GNS_LO_DEFAULT, &print_did_document, NULL); 195 GNUNET_SCHEDULER_add_now (cleanup, NULL);
196 ret = 0;
197 return;
198 }
276} 199}
277 200
278 201
@@ -320,7 +243,8 @@ remove_did_document_namestore_cb (void *cls, int32_t success, const char *emgs)
320 ret = 0; 243 ret = 0;
321 return; 244 return;
322 } 245 }
323 } else { 246 }
247 else {
324 printf ("Something went wrong when deleting the DID Document\n"); 248 printf ("Something went wrong when deleting the DID Document\n");
325 249
326 if (emgs != NULL) 250 if (emgs != NULL)
@@ -328,7 +252,7 @@ remove_did_document_namestore_cb (void *cls, int32_t success, const char *emgs)
328 printf ("%s\n", emgs); 252 printf ("%s\n", emgs);
329 } 253 }
330 254
331 GNUNET_SCHEDULER_add_now (&cleanup, NULL); 255 GNUNET_SCHEDULER_add_now (cleanup, NULL);
332 ret = 0; 256 ret = 0;
333 return; 257 return;
334 } 258 }
@@ -382,259 +306,123 @@ remove_did_document (remove_did_document_callback cont, void *cls)
382 } 306 }
383} 307}
384 308
309// Needed because create_did_ego_lookup_cb() and
310// create_did_ego_create_cb() can call each other
311static void create_did_ego_lockup_cb ();
385 312
386/** 313/**
387 * @brief Create a did generate did object 314 * @brief Create a DID(-Document). Called after DID has been created
315 * Prints status and the DID.
388 * 316 *
389 * @param pkey
390 * @return void* Return pointer to the DID Document
391 */ 317 */
392char * 318static void
393create_did_generate (struct GNUNET_IDENTITY_PublicKey pkey) 319create_did_cb (enum GNUNET_GenericReturnValue status, void *cls)
394{ 320{
395 /* FIXME-MSC: I would prefer constants instead of magic numbers */ 321 if (GNUNET_OK == status)
396 char *pkey_str; // Convert public key to string
397 char did_str[71]; // 58 + 12 + 1 = 71
398 char *didd_str;
399 char verify_id_str[77]; // did_str len + "#key-1" = 71 + 6 = 77
400 char *pkey_multibase_str;
401
402 /* FIXME-MSC: This screams for a GNUNET_DID_identity_key_to_string() */
403 char *b64;
404 char pkx[34];
405 pkx[0] = 0xed;
406 pkx[1] = 0x01;
407 memcpy (pkx + 2, &(pkey.eddsa_key), sizeof(pkey.eddsa_key));
408 GNUNET_STRINGS_base64_encode (pkx, sizeof(pkx), &b64);
409
410 GNUNET_asprintf (&pkey_multibase_str, "u%s", b64);
411
412 json_t *didd;
413 json_t *did_json;
414 json_t *pkey_multibase_json;
415 json_t *context_json;
416 json_t *context_1_json;
417 json_t *context_2_json;
418 json_t *verify_json;
419 json_t *verify_1_json;
420 json_t *verify_1_type_json;
421 json_t *verify_1_id_json;
422 json_t *verify_relative_ref_json;
423 json_t *auth_json;
424 json_t *assert_json;
425
426 /* FIXME-MSC: This screams for GNUNET_DID_identity_to_did() */
427 pkey_str = GNUNET_IDENTITY_public_key_to_string (&pkey); // Convert public key to string
428 sprintf (did_str, "did:reclaim:%s", pkey_str); // Convert the public key to a DID str
429 sprintf (verify_id_str, "did:reclaim:%s#key-1", pkey_str); // Convert the public key to a DID str
430
431 // sprintf(pkey_multibase_str, "V%s", pkey_str); // Convert the public key to MultiBase data format
432
433 /* FIXME-MSC: This is effectively creating a DID Document default template for
434 * the initial document.
435 * Maybe this can be refactored to generate such a template for an identity?
436 * Even if higher layers add/modify it, there should probably still be a
437 * GNUNET_DID_document_template_from_identity()
438 */
439 // Create Json Strings
440 did_json = json_string (did_str);
441 pkey_multibase_json = json_string (pkey_multibase_str);
442
443 context_1_json = json_string ("https://www.w3.org/ns/did/v1");
444 context_2_json = json_string (
445 "https://w3id.org/security/suites/ed25519-2020/v1");
446 verify_1_id_json = json_string (verify_id_str);
447 verify_1_type_json = json_string ("Ed25519VerificationKey2020");
448
449 // Add a relative DID URL to reference a verifiation method
450 // https://www.w3.org/TR/did-core/#relative-did-urls`
451 verify_relative_ref_json = json_string ("#key-1");
452
453 // Create DID Document
454 didd = json_object ();
455
456 // Add context
457 context_json = json_array ();
458 json_array_append (context_json, context_1_json);
459 json_array_append (context_json, context_2_json);
460 json_object_set (didd, "@context", context_json);
461
462 // Add id
463 json_object_set (didd, "id", did_json);
464
465 // Add verification method
466 verify_json = json_array ();
467 verify_1_json = json_object ();
468 json_object_set (verify_1_json, "id", verify_1_id_json);
469 json_object_set (verify_1_json, "type", verify_1_type_json);
470 json_object_set (verify_1_json, "controller", did_json);
471 json_object_set (verify_1_json, "publicKeyMultiBase", pkey_multibase_json);
472 json_array_append (verify_json, verify_1_json);
473 json_object_set (didd, "verificationMethod", verify_json);
474
475 // Add authentication method
476 auth_json = json_array ();
477 json_array_append (auth_json, verify_relative_ref_json);
478 json_object_set (didd, "authentication", auth_json);
479
480 // Add assertion method to issue a Verifiable Credential
481 assert_json = json_array ();
482 json_array_append (assert_json, verify_relative_ref_json);
483 json_object_set (didd, "assertionMethod", assert_json);
484
485 // Encode DID Document as JSON string
486 didd_str = json_dumps (didd, JSON_INDENT (2));
487 if (didd_str == NULL)
488 { 322 {
489 printf ("DID Document could not be encoded"); 323 printf ("DID has been created.\n%s\n", (char *) cls);
490 GNUNET_SCHEDULER_add_now (&cleanup, NULL); 324 free (cls);
325 ret = 0;
326 }
327 else
328 {
329 printf ("An error occured while creating the DID.\n");
491 ret = 1; 330 ret = 1;
492 return NULL;
493 } 331 }
494 332
495 // TODO: MORE FREEEEEEEE
496 /* FIXME-MSC: json_t's are free'd using "json_decref". Also json_t usually
497 * keeps a reference counter. Check jansson docs for how to use it.
498 * Also: Use valgrind to find leaks.
499 */
500 free (pkey_multibase_str);
501 free (b64);
502
503 free (didd);
504 free (did_json);
505 free (pkey_multibase_json);
506 free (context_json);
507 free (context_1_json);
508 free (context_2_json);
509 free (verify_json);
510 free (verify_1_json);
511 free (verify_1_type_json);
512 free (verify_1_id_json);
513 free (auth_json);
514 free (assert_json);
515 free (verify_relative_ref_json);
516
517 return didd_str;
518}
519
520/**
521 * @brief Create a DID. Store DID in Namestore cb
522 *
523 */
524static void
525create_did_store_cb (void *cls, int32_t success, const char *emsg)
526{
527 GNUNET_SCHEDULER_add_now (&cleanup, NULL); 333 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
528 ret = 0;
529 return; 334 return;
530} 335}
531 336
532/** 337/**
533 * @brief Create a did. Store DID in Namestore 338 * @brief Create a DID(-Document) - Called after a new Identity has been created.
534 *
535 * @param didd_str String endoced DID Docuement
536 * @param ego Identity whos DID Document is stored
537 */ 339 */
538static void 340static void
539create_did_store (char *didd_str, struct GNUNET_IDENTITY_Ego *ego) 341create_did_ego_create_cb (void *cls,
342 const struct GNUNET_IDENTITY_PrivateKey *pk,
343 const char *emsg)
540{ 344{
541 345 if (emsg != NULL)
542 struct GNUNET_TIME_Relative expire_time;
543 struct GNUNET_GNSRECORD_Data record_data;
544 const struct GNUNET_IDENTITY_PrivateKey *skey;
545
546 if (GNUNET_STRINGS_fancy_time_to_relative ((NULL != expire) ?
547 expire :
548 GNUNET_DID_DEFAULT_DID_DOCUMENT_EXPIRATION_TIME,
549 &expire_time) == GNUNET_OK)
550 { 346 {
551 record_data.data = didd_str; 347 printf ("%s\n", emsg);
552 record_data.expiration_time = expire_time.rel_value_us;
553 record_data.data_size = strlen (didd_str) + 1;
554 record_data.record_type = GNUNET_GNSRECORD_typename_to_number ("TXT"),
555 record_data.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
556
557 skey = GNUNET_IDENTITY_ego_get_private_key (ego);
558
559 GNUNET_NAMESTORE_records_store (namestore_handle,
560 skey,
561 GNUNET_GNS_EMPTY_LABEL_AT,
562 1, //FIXME what if GNUNET_GNS_EMPTY_LABEL_AT has records
563 &record_data,
564 &create_did_store_cb,
565 NULL);
566 }
567 else {
568 printf ("Failed to read given expiration time\n");
569 GNUNET_SCHEDULER_add_now (&cleanup, NULL); 348 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
570 ret = 1; 349 ret = 1;
571 return; 350 return;
572 } 351 }
352
353 GNUNET_IDENTITY_ego_lookup (my_cfg,
354 egoname,
355 &create_did_ego_lockup_cb,
356 NULL);
573} 357}
574 358
575/** 359/**
576 * @brief Create a did ego lockup cb 360 * @brief Create a DID(-Document). Called after ego lookup
577 * 361 *
578 * @param cls
579 * @param ego
580 */ 362 */
581static void 363static void
582create_did_ego_lockup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) 364create_did_ego_lockup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
583{ 365{
584 struct GNUNET_IDENTITY_PublicKey pkey;
585 char *didd_str;
586
587 if (ego == NULL) 366 if (ego == NULL)
588 { 367 {
589 printf ("EGO not found\n"); 368 // If Ego was not found. Create new one first
590 GNUNET_SCHEDULER_add_now (&cleanup, NULL); 369 printf ("Ego was not found. Creating new one.\n");
591 ret = 1; 370 GNUNET_IDENTITY_create (identity_handle,
592 return; 371 egoname,
593 } 372 NULL,
594 373 GNUNET_IDENTITY_TYPE_EDDSA,
595 GNUNET_IDENTITY_ego_get_public_key (ego, &pkey); 374 &create_did_ego_create_cb,
596 375 egoname);
597 if (ntohl (pkey.type) != GNUNET_GNSRECORD_TYPE_EDKEY)
598 {
599 printf ("The EGO has to have an EDDSA key pair\n");
600 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
601 ret = 1;
602 return;
603 } 376 }
604 377 else
605 if (didd != NULL)
606 { 378 {
607 printf ( 379 char *did = DID_identity_to_did (ego);
608 "DID Docuement is read from \"did-document\" argument (EXPERIMENTAL)\n"); 380 void *cls = malloc (strlen (did) + 1);
609 didd_str = strdup (didd); 381 struct GNUNET_TIME_Relative expire_relative;
610 }
611 else {
612 // Generate DID Docuement from public key
613 didd_str = create_did_generate (pkey);
614 }
615
616 // Print DID Document to stdout
617 printf ("%s\n", didd_str);
618 382
619 // Store the DID Document 383 if (expire == NULL)
620 create_did_store (didd_str, ego); 384 {
385 GNUNET_STRINGS_fancy_time_to_relative (
386 DID_DOCUMENT_DEFAULT_EXPIRATION_TIME, &expire_relative);
387 }
388 else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (expire,
389 &
390 expire_relative))
391 {
392 printf ("Failed to read given expiration time\n");
393 GNUNET_SCHEDULER_add_now (cleanup, NULL);
394 ret = 1;
395 return;
396 }
621 397
622 // Save DID Document String to GNS 398 strcpy (cls, did);
623 free (didd_str); 399 // TODO: Add DID_document argument
400 if (GNUNET_OK != DID_create (ego,
401 NULL,
402 &expire_relative,
403 namestore_handle,
404 create_did_cb,
405 cls))
406 {
407 printf ("An error occured while creating the DID.\n");
408 ret = 1;
409 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
410 return;
411 }
412 }
624} 413}
625 414
626/** 415/**
627 * @brief Create a did document - Create a new identity first 416 * @brief Create a DID(-Document).
417 *
628 */ 418 */
629static void 419static void
630create_did_document_ego_create_cb (void *cls, 420create_did ()
631 const struct GNUNET_IDENTITY_PrivateKey *pk,
632 const char *emsg)
633{ 421{
634 422 // Ego name to be set
635 if (emsg != NULL) 423 if (egoname == NULL)
636 { 424 {
637 printf ("%s\n", emsg); 425 printf ("Set the Ego argument to create a new DID(-Document)\n");
638 GNUNET_SCHEDULER_add_now (&cleanup, NULL); 426 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
639 ret = 1; 427 ret = 1;
640 return; 428 return;
@@ -646,31 +434,6 @@ create_did_document_ego_create_cb (void *cls,
646 NULL); 434 NULL);
647} 435}
648 436
649/**
650 * @brief Create a did document
651 *
652 */
653static void
654create_did_document ()
655{
656 if ((egoname != NULL) && (expire != NULL))
657 {
658 GNUNET_IDENTITY_create (identity_handle,
659 egoname,
660 NULL,
661 GNUNET_IDENTITY_TYPE_EDDSA,
662 &create_did_document_ego_create_cb,
663 egoname);
664 }
665 else {
666 printf (
667 "Set the EGO and the Expiration-time argument to create a new DID(-Document)\n");
668 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
669 ret = 1;
670 return;
671 }
672}
673
674 437
675/** 438/**
676 * @brief Replace a DID Docuemnt. Callback function after ego lockup 439 * @brief Replace a DID Docuemnt. Callback function after ego lockup
@@ -681,7 +444,7 @@ create_did_document ()
681static void 444static void
682replace_did_document_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) 445replace_did_document_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
683{ 446{
684 create_did_store (didd, ego); 447 // create_did_store (didd, ego);
685} 448}
686 449
687/** 450/**
@@ -721,13 +484,15 @@ replace_did_document ()
721static void 484static void
722post_ego_iteration (void *cls) 485post_ego_iteration (void *cls)
723{ 486{
487 // TODO: Check that only one argument is set
488
724 if (1 == replace) 489 if (1 == replace)
725 { 490 {
726 replace_did_document (); 491 replace_did_document ();
727 } 492 }
728 else if (1 == get) 493 else if (1 == get)
729 { 494 {
730 resolve_did_document (); 495 resolve_did ();
731 } 496 }
732 else if (1 == remove_did) 497 else if (1 == remove_did)
733 { 498 {
@@ -735,7 +500,7 @@ post_ego_iteration (void *cls)
735 } 500 }
736 else if (1 == create) 501 else if (1 == create)
737 { 502 {
738 create_did_document (); 503 create_did ();
739 } 504 }
740 else { 505 else {
741 // No Argument found 506 // No Argument found
@@ -760,19 +525,21 @@ process_dids (void *cls, struct GNUNET_IDENTITY_Ego *ego,
760 GNUNET_SCHEDULER_add_now (&post_ego_iteration, NULL); 525 GNUNET_SCHEDULER_add_now (&post_ego_iteration, NULL);
761 return; 526 return;
762 } 527 }
763 if (NULL == name) 528
764 return; 529 // if (NULL == name)
765 if ((1 == create) && 530 // return;
766 (0 == strncmp (name, egoname, strlen (egoname))) && 531 // if ((1 == create) &&
767 (1 != ego_exists)) 532 // (0 == strncmp (name, egoname, strlen (egoname))) &&
768 { 533 // (1 != ego_exists))
769 fprintf(stderr, "%s already exists!\n", egoname); 534 // {
770 ego_exists = 1; 535 // fprintf (stderr, "%s already exists!\n", egoname);
771 return; 536 // ego_exists = 1;
772 } 537 // return;
538 // }
539
773 if (1 == show_all) 540 if (1 == show_all)
774 { 541 {
775 did_str = DID_ego_to_did (ego); 542 did_str = DID_identity_to_did (ego);
776 printf ("%s\n", did_str); 543 printf ("%s\n", did_str);
777 GNUNET_free (did_str); 544 GNUNET_free (did_str);
778 return; 545 return;
@@ -781,7 +548,7 @@ process_dids (void *cls, struct GNUNET_IDENTITY_Ego *ego,
781 { 548 {
782 if (0 == strncmp (name, egoname, strlen (egoname))) 549 if (0 == strncmp (name, egoname, strlen (egoname)))
783 { 550 {
784 did_str = DID_ego_to_did (ego); 551 did_str = DID_identity_to_did (ego);
785 printf ("%s\n", did_str); 552 printf ("%s\n", did_str);
786 GNUNET_free (did_str); 553 GNUNET_free (did_str);
787 return; 554 return;
@@ -839,10 +606,6 @@ main (int argc, char *const argv[])
839 gettext_noop ( 606 gettext_noop (
840 "Get the DID Document associated with the given DID"), 607 "Get the DID Document associated with the given DID"),
841 &get), 608 &get),
842 GNUNET_GETOPT_option_flag ('s',
843 "show",
844 gettext_noop ("Show the DID for a given ego"),
845 &show),
846 GNUNET_GETOPT_option_flag ('r', 609 GNUNET_GETOPT_option_flag ('r',
847 "remove", 610 "remove",
848 gettext_noop ( 611 gettext_noop (
@@ -852,9 +615,13 @@ main (int argc, char *const argv[])
852 "replace", 615 "replace",
853 gettext_noop ("Replace the DID Document."), 616 gettext_noop ("Replace the DID Document."),
854 &replace), 617 &replace),
618 GNUNET_GETOPT_option_flag ('s',
619 "show",
620 gettext_noop ("Show the DID for a given ego"),
621 &show),
855 GNUNET_GETOPT_option_flag ('A', 622 GNUNET_GETOPT_option_flag ('A',
856 "--show-all", 623 "show-all",
857 gettext_noop ("Replace the DID Document."), 624 gettext_noop ("Show egos with DIDs"),
858 &show_all), 625 &show_all),
859 GNUNET_GETOPT_option_string ('d', 626 GNUNET_GETOPT_option_string ('d',
860 "did", 627 "did",
@@ -863,7 +630,7 @@ main (int argc, char *const argv[])
863 "The Decentralized Identity (DID)"), 630 "The Decentralized Identity (DID)"),
864 &did), 631 &did),
865 GNUNET_GETOPT_option_string ('D', 632 GNUNET_GETOPT_option_string ('D',
866 "--did-document", 633 "did-document",
867 "JSON", 634 "JSON",
868 gettext_noop ( 635 gettext_noop (
869 "The DID Document to store in GNUNET"), 636 "The DID Document to store in GNUNET"),
@@ -885,8 +652,7 @@ main (int argc, char *const argv[])
885 if (GNUNET_OK != GNUNET_PROGRAM_run (argc, 652 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
886 argv, 653 argv,
887 "gnunet-did", 654 "gnunet-did",
888 _ ( 655 "Manage Decentralized Identities (DIDs)",
889 "Manage Decentralized Identities (DIDs)"),
890 options, 656 options,
891 &run, 657 &run,
892 NULL)) 658 NULL))
diff --git a/src/reclaim/test_did_helper.c b/src/reclaim/test_did_helper.c
new file mode 100644
index 000000000..2f72c3496
--- /dev/null
+++ b/src/reclaim/test_did_helper.c
@@ -0,0 +1,131 @@
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/test_did_helper.c
23 * @brief Unit tests for the helper library for DID related functions
24 * @author Tristan Schwieren
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gns_service.h"
31#include "gnunet_gnsrecord_lib.h"
32#include "did_helper.h"
33#include "jansson.h"
34
35static const char test_skey_bytes[32] = {
36 0x9b, 0x93, 0x7b, 0x81, 0x32, 0x2d, 0x81, 0x6c,
37 0xfa, 0xb9, 0xd5, 0xa3, 0xba, 0xac, 0xc9, 0xb2,
38 0xa5, 0xfe, 0xbe, 0x4b, 0x14, 0x9f, 0x12, 0x6b,
39 0x36, 0x30, 0xf9, 0x3a, 0x29, 0x52, 0x70, 0x17
40};
41
42// TODO: Create a did manual from private key / independet of implementation
43static const char *test_did =
44 "did:reclaim:000G0509BYD1MPAXVSTNV0KRD1JAT0YZMPJFQNM869B66S72PSF17K4Y8G";
45
46static const char *test_multibase_key =
47 "u7QEJX5oaWV3edV2CeGhkrQPfpaT71ogyVmNk4rZeE8yeRA";
48
49static const char *test_did_document_format_str =
50 "{\"@context\":[\"https://www.w3.org/ns/did/v1\",\
51 \"https://w3id.org/security/suites/ed25519-2020/v1\"],\
52 \"id\":\"%s\",\
53 \"verificationMethod\":[{\
54 \"id\":\"%s#key-1\",\
55 \"type\":\"Ed25519VerificationKey2020\",\
56 \"controller\":\"%s\",\
57 \"publicKeyMultibase\":\"%s\"}],\
58 \"authentication\":[\"#key-1\"],\
59 \"assertionMethod\":[\"#key-1\"]}";
60
61static struct GNUNET_IDENTITY_PrivateKey test_skey;
62static struct GNUNET_IDENTITY_PublicKey test_pkey;
63static struct json_t *test_did_document;
64static char *test_did_document_str;
65
66void
67test_GNUNET_DID_pkey_to_did ()
68{
69 char *str_did;
70 str_did = DID_pkey_to_did (&test_pkey);
71 GNUNET_assert (strcmp ((char *) test_did, str_did) == 0);
72}
73
74void
75test_GNUNET_DID_did_to_pkey ()
76{
77 struct GNUNET_IDENTITY_PublicKey pkey;
78 DID_did_to_pkey ((char *) test_did, &pkey);
79
80 GNUNET_assert (test_pkey.type = pkey.type);
81 GNUNET_assert (strcmp (pkey.eddsa_key.q_y,
82 test_pkey.eddsa_key.q_y) == 0);
83}
84
85// void
86// test_GNUNET_DID_key_covert_multibase_base64_to_gnunet ();
87
88void
89test_GNUNET_DID_key_covert_gnunet_to_multibase_base64 ()
90{
91 char *multibase_key;
92 multibase_key = DID_key_covert_gnunet_to_multibase_base64 (&test_pkey);
93
94 GNUNET_assert (strcmp (test_multibase_key, multibase_key) == 0);
95}
96
97void
98test_GNUNET_DID_pkey_to_did_document ()
99{
100 struct json_t *did_document;
101 char *did_document_str = DID_pkey_to_did_document (&test_pkey);
102 did_document = json_loads (did_document_str, JSON_DECODE_ANY, NULL);
103 GNUNET_assert (json_equal (test_did_document, did_document) == 1);
104}
105
106int
107main ()
108{
109 // Setup key
110 test_skey.type = htonl (GNUNET_IDENTITY_TYPE_EDDSA);
111 memcpy (&(test_skey.eddsa_key),
112 test_skey_bytes,
113 sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
114 GNUNET_IDENTITY_key_get_public (&test_skey, &test_pkey);
115
116 // Setup did document
117 GNUNET_asprintf (&test_did_document_str,
118 test_did_document_format_str,
119 test_did,
120 test_did,
121 test_did,
122 test_multibase_key);
123 test_did_document = json_loads (test_did_document_str, JSON_DECODE_ANY, NULL);
124
125 // Do tests
126 test_GNUNET_DID_pkey_to_did ();
127 test_GNUNET_DID_did_to_pkey ();
128 test_GNUNET_DID_pkey_to_did_document ();
129 test_GNUNET_DID_key_covert_gnunet_to_multibase_base64 ();
130 return 0;
131} \ No newline at end of file