diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-08-31 17:59:47 +0200 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-08-31 17:59:47 +0200 |
commit | 4a2c758df3b20104580fc5ff9efc1d6cd7237bd0 (patch) | |
tree | 122fac6e24f9c8f5bbdc2824d06a6166f976033a /src/reclaim | |
parent | cc70504a2f2756107976924843fe6b39b9ac94cb (diff) | |
parent | 6f72f195810305071da63061a84fed035d7368d6 (diff) | |
download | gnunet-4a2c758df3b20104580fc5ff9efc1d6cd7237bd0.tar.gz gnunet-4a2c758df3b20104580fc5ff9efc1d6cd7237bd0.zip |
-fixup merge
Diffstat (limited to 'src/reclaim')
-rw-r--r-- | src/reclaim/.gitignore | 2 | ||||
-rw-r--r-- | src/reclaim/Makefile.am | 44 | ||||
-rw-r--r-- | src/reclaim/did_core.c | 267 | ||||
-rw-r--r-- | src/reclaim/did_core.h | 138 | ||||
-rw-r--r-- | src/reclaim/did_helper.c | 203 | ||||
-rw-r--r-- | src/reclaim/did_helper.h | 74 | ||||
-rw-r--r-- | src/reclaim/gnunet-did.c | 482 | ||||
-rw-r--r-- | src/reclaim/test_did_helper.c | 131 |
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 @@ | |||
1 | gnunet-reclaim | 1 | gnunet-reclaim |
2 | gnunet-service-reclaim | 2 | gnunet-service-reclaim |
3 | gnunet-did | 3 | gnunet-did |
4 | test_did_helper | ||
5 | test_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 | ||
40 | lib_LTLIBRARIES = \ | 40 | lib_LTLIBRARIES = \ |
41 | libgnunetreclaim.la | 41 | libgnunetreclaim.la \ |
42 | libgnunetdid.la | ||
42 | plugin_LTLIBRARIES = \ | 43 | plugin_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 | ||
146 | libgnunetdid_la_SOURCES = \ | ||
147 | did_helper.c \ | ||
148 | did_helper.h \ | ||
149 | did_core.h \ | ||
150 | did_core.c | ||
151 | libgnunetdid_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) | ||
159 | libgnunetdid_la_LDFLAGS = \ | ||
160 | $(GN_LIB_LDFLAGS) \ | ||
161 | -version-info 0:0:0 | ||
145 | 162 | ||
146 | libgnunet_plugin_reclaim_attribute_basic_la_SOURCES = \ | 163 | libgnunet_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 | ||
196 | gnunet_did_SOURCES = \ | 213 | gnunet_did_SOURCES = \ |
197 | gnunet-did.c \ | 214 | gnunet-did.c |
198 | did_misc.c \ | ||
199 | did.h | ||
200 | gnunet_did_LDADD = \ | 215 | gnunet_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 | ||
209 | test_w3c_ed25519_2020_SOURCES = \ | 225 | test_did_helper_SOURCES = \ |
210 | test_w3c_ed25519_2020.c | 226 | test_did_helper.c |
211 | test_w3c_ed25519_2020_LDADD = \ | 227 | test_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 | ||
214 | check_SCRIPTS = \ | 236 | check_SCRIPTS = \ |
215 | test_reclaim_attribute.sh \ | 237 | test_reclaim_attribute.sh \ |
@@ -218,9 +240,11 @@ check_SCRIPTS = \ | |||
218 | 240 | ||
219 | check_PROGRAMS = \ | 241 | check_PROGRAMS = \ |
220 | test_reclaim_attribute \ | 242 | test_reclaim_attribute \ |
221 | test_w3c_ed25519_2020 | 243 | test_did_helper |
222 | 244 | ||
223 | if ENABLE_TEST_RUN | 245 | if 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) | ||
226 | endif | 250 | endif |
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 | |||
32 | struct DID_resolve_return | ||
33 | { | ||
34 | DID_resolve_callback *cb; | ||
35 | void *cls; | ||
36 | }; | ||
37 | |||
38 | struct 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 | */ | ||
57 | static void | ||
58 | DID_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 | */ | ||
88 | enum GNUNET_GenericReturnValue | ||
89 | DID_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 | |||
124 | static void | ||
125 | DID_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 | |||
145 | struct 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 | |||
153 | static void | ||
154 | DID_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 | */ | ||
222 | enum GNUNET_GenericReturnValue | ||
223 | DID_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 | */ | ||
49 | typedef 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 | */ | ||
60 | typedef 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 | */ | ||
74 | enum GNUNET_GenericReturnValue | ||
75 | DID_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 | */ | ||
92 | enum GNUNET_GenericReturnValue | ||
93 | DID_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 | */ | ||
111 | enum GNUNET_GenericReturnValue | ||
112 | DID_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 | */ | ||
131 | enum GNUNET_GenericReturnValue | ||
132 | DID_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 | */ | ||
44 | char* | ||
45 | DID_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 | */ | ||
66 | char* | ||
67 | DID_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 | */ | ||
78 | enum GNUNET_GenericReturnValue | ||
79 | DID_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 | */ | ||
100 | struct GNUNET_IDENTITY_PublicKey * | ||
101 | GNUNET_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 | */ | ||
109 | char * | ||
110 | DID_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 | */ | ||
137 | char * | ||
138 | DID_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 | */ | ||
196 | char * | ||
197 | DID_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 | */ | ||
33 | char * | ||
34 | DID_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 | */ | ||
42 | char * | ||
43 | DID_identity_to_did (struct GNUNET_IDENTITY_Ego *ego); | ||
44 | |||
45 | /** | ||
46 | * @brief Return the public key of a DID | ||
47 | */ | ||
48 | enum GNUNET_GenericReturnValue | ||
49 | DID_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 | */ | ||
60 | char * | ||
61 | DID_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 | */ | ||
67 | char * | ||
68 | DID_pkey_to_did_document (struct GNUNET_IDENTITY_PublicKey *pkey); | ||
69 | |||
70 | /** | ||
71 | * @brief Generate the default DID document for a GNUNET ego | ||
72 | */ | ||
73 | char * | ||
74 | DID_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 | */ | ||
155 | static void | ||
156 | get_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 | */ | ||
180 | static void | ||
181 | get_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 | */ | ||
204 | static void | ||
205 | get_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 | */ |
224 | static void | 159 | static void |
225 | print_did_document ( | 160 | print_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 | */ |
259 | static void | 179 | static void |
260 | resolve_did_document () | 180 | resolve_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 | ||
311 | static 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 | */ |
392 | char * | 318 | static void |
393 | create_did_generate (struct GNUNET_IDENTITY_PublicKey pkey) | 319 | create_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 | */ | ||
524 | static void | ||
525 | create_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 | */ |
538 | static void | 340 | static void |
539 | create_did_store (char *didd_str, struct GNUNET_IDENTITY_Ego *ego) | 341 | create_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 | */ |
581 | static void | 363 | static void |
582 | create_did_ego_lockup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) | 364 | create_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 | */ |
629 | static void | 419 | static void |
630 | create_did_document_ego_create_cb (void *cls, | 420 | create_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 | */ | ||
653 | static void | ||
654 | create_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 () | |||
681 | static void | 444 | static void |
682 | replace_did_document_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) | 445 | replace_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 () | |||
721 | static void | 484 | static void |
722 | post_ego_iteration (void *cls) | 485 | post_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 | |||
35 | static 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 | ||
43 | static const char *test_did = | ||
44 | "did:reclaim:000G0509BYD1MPAXVSTNV0KRD1JAT0YZMPJFQNM869B66S72PSF17K4Y8G"; | ||
45 | |||
46 | static const char *test_multibase_key = | ||
47 | "u7QEJX5oaWV3edV2CeGhkrQPfpaT71ogyVmNk4rZeE8yeRA"; | ||
48 | |||
49 | static 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 | |||
61 | static struct GNUNET_IDENTITY_PrivateKey test_skey; | ||
62 | static struct GNUNET_IDENTITY_PublicKey test_pkey; | ||
63 | static struct json_t *test_did_document; | ||
64 | static char *test_did_document_str; | ||
65 | |||
66 | void | ||
67 | test_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 | |||
74 | void | ||
75 | test_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 | |||
88 | void | ||
89 | test_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 | |||
97 | void | ||
98 | test_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 | |||
106 | int | ||
107 | main () | ||
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 | ||