aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/gnunet-did.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/gnunet-did.c')
-rw-r--r--src/reclaim/gnunet-did.c896
1 files changed, 0 insertions, 896 deletions
diff --git a/src/reclaim/gnunet-did.c b/src/reclaim/gnunet-did.c
deleted file mode 100644
index 4c5704d44..000000000
--- a/src/reclaim/gnunet-did.c
+++ /dev/null
@@ -1,896 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2022 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 * FIXME: Do we only want to handle EdDSA identities?
23 * TODO: Own GNS record type
24 * TODO: Fix overwrite of records in @ if present look for other with same sub
25 * TODO. Tests
26 * TODO: Move constants to did.h
27 * FIXME: Remove and lookup require differnt representations (did vs egoname)
28 */
29
30/**
31 * @author Tristan Schwieren
32 * @file src/did/gnunet-did.c
33 * @brief DID Method Wrapper
34 *
35 */
36#include "platform.h"
37#include "gnunet_util_lib.h"
38#include "gnunet_namestore_service.h"
39#include "gnunet_gns_service.h"
40#include "gnunet_gnsrecord_lib.h"
41#include "jansson.h"
42#include "did.h"
43
44#define GNUNET_DID_DEFAULT_DID_DOCUMENT_EXPIRATION_TIME "1d"
45
46/**
47 * return value
48 */
49static int ret;
50
51/**
52 * Replace DID Document Flag
53 */
54static int replace;
55
56/**
57 * Remove DID Document Flag
58 */
59static int remove_did;
60
61/**
62 * Get DID Documement for DID Flag
63 */
64static int get;
65
66/**
67 * Create DID Document Flag
68 */
69static int create;
70
71/**
72 * Show DID for Ego Flag
73 */
74static int show;
75
76/**
77 * Show DID for Ego Flag
78 */
79static int show_all;
80
81/**
82 * DID Attribut String
83 */
84static char *did;
85
86/**
87 * DID Document Attribut String
88 */
89static char *didd;
90
91/**
92 * Ego Attribut String
93 */
94static char *egoname;
95
96/**
97 * DID Document expiration Date Attribut String
98 */
99static char *expire;
100
101/*
102 * Handle to the GNS service
103 */
104static struct GNUNET_GNS_Handle *gns_handle;
105
106/*
107 * Handle to the NAMESTORE service
108 */
109static struct GNUNET_NAMESTORE_Handle *namestore_handle;
110
111/*
112 * Handle to the IDENTITY service
113 */
114static struct GNUNET_IDENTITY_Handle *identity_handle;
115
116
117/*
118 * The configuration
119 */
120const static struct GNUNET_CONFIGURATION_Handle *my_cfg;
121
122/**
123 * Give ego exists
124 */
125static int ego_exists = 0;
126
127/**
128 * @brief Disconnect and shutdown
129 * @param cls closure
130 */
131static void
132cleanup (void *cls)
133{
134 if (NULL != gns_handle)
135 GNUNET_GNS_disconnect (gns_handle);
136 if (NULL != namestore_handle)
137 GNUNET_NAMESTORE_disconnect (namestore_handle);
138 if (NULL != identity_handle)
139 GNUNET_IDENTITY_disconnect (identity_handle);
140
141 GNUNET_free (did);
142 GNUNET_free (didd);
143 GNUNET_free (egoname);
144 GNUNET_free (expire);
145
146 GNUNET_SCHEDULER_shutdown ();
147}
148
149/**
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.
218 * Fails if there is more than one DID record.
219 *
220 * @param cls closure
221 * @param rd_count number of records in @a rd
222 * @param rd the records in the reply
223 */
224static void
225print_did_document (
226 void *cls,
227 uint32_t rd_count,
228 const struct GNUNET_GNSRECORD_Data *rd)
229{
230 /*
231 * FIXME-MSC: The user may decide to put other records here.
232 * In general I am fine with the constraint here, but not when
233 * we move it to "@"
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
251 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
252 ret = 0;
253 return;
254}
255
256/**
257 * @brief Resolve a DID given by the user.
258 */
259static void
260resolve_did_document ()
261{
262 struct GNUNET_IDENTITY_PublicKey pkey;
263
264 if (did == NULL)
265 {
266 printf ("Set DID option to resolve DID\n");
267 GNUNET_SCHEDULER_add_now (cleanup, NULL);
268 ret = 1;
269 return;
270 }
271
272 get_pkey_from_attr_did (&pkey);
273
274 GNUNET_GNS_lookup (gns_handle, GNUNET_GNS_EMPTY_LABEL_AT, &pkey, GNUNET_DNSPARSER_TYPE_TXT,
275 GNUNET_GNS_LO_DEFAULT, &print_did_document, NULL);
276}
277
278
279/**
280 * @brief Signature of a callback function that is called after a did has been removed
281 */
282typedef void
283(*remove_did_document_callback) (void *cls);
284
285/**
286 * @brief A Structure containing a cont and cls. Can be passed as a cls to a callback function
287 *
288 */
289struct Event
290{
291 remove_did_document_callback cont;
292 void *cls;
293};
294
295/**
296 * @brief Implements the GNUNET_NAMESTORE_ContinuationWithStatus
297 * Calls the callback function and cls in the event struct
298 *
299 * @param cls closure containing the event struct
300 * @param success
301 * @param emgs
302 */
303static void
304remove_did_document_namestore_cb (void *cls, int32_t success, const char *emgs)
305{
306 struct Event *event;
307
308 if (success != GNUNET_SYSERR)
309 {
310 event = (struct Event *) cls;
311
312 if (event->cont != NULL)
313 {
314 event->cont (event->cls);
315 free (event);
316 }
317 else {
318 free (event);
319 GNUNET_SCHEDULER_add_now (cleanup, NULL);
320 ret = 0;
321 return;
322 }
323 } else {
324 printf ("Something went wrong when deleting the DID Document\n");
325
326 if (emgs != NULL)
327 {
328 printf ("%s\n", emgs);
329 }
330
331 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
332 ret = 0;
333 return;
334 }
335}
336
337/**
338 * @brief Callback called after the ego has been locked up
339 *
340 * @param cls closure
341 * @param ego the ego returned by the identity service
342 */
343static void
344remove_did_document_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
345{
346 const struct GNUNET_IDENTITY_PrivateKey *skey =
347 GNUNET_IDENTITY_ego_get_private_key (ego);
348
349 GNUNET_NAMESTORE_records_store (namestore_handle,
350 skey,
351 GNUNET_GNS_EMPTY_LABEL_AT,
352 0,
353 NULL,
354 &remove_did_document_namestore_cb,
355 cls);
356}
357
358/**
359 * @brief Remove a DID Document
360 */
361static void
362remove_did_document (remove_did_document_callback cont, void *cls)
363{
364 struct Event *event;
365
366 if (egoname == NULL)
367 {
368 printf ("Remove requieres an ego option\n");
369 GNUNET_SCHEDULER_add_now (cleanup, NULL);
370 ret = 1;
371 return;
372 }
373 else {
374 event = malloc (sizeof(*event));
375 event->cont = cont;
376 event->cls = cls;
377
378 GNUNET_IDENTITY_ego_lookup (my_cfg,
379 egoname,
380 &remove_did_document_ego_lookup_cb,
381 (void *) event);
382 }
383}
384
385
386/**
387 * @brief Create a did generate did object
388 *
389 * @param pkey
390 * @return void* Return pointer to the DID Document
391 */
392char *
393create_did_generate (struct GNUNET_IDENTITY_PublicKey pkey)
394{
395 /* FIXME-MSC: I would prefer constants instead of magic numbers */
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 {
489 printf ("DID Document could not be encoded");
490 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
491 ret = 1;
492 return NULL;
493 }
494
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);
528 ret = 0;
529 return;
530}
531
532/**
533 * @brief Create a did. Store DID in Namestore
534 *
535 * @param didd_str String endoced DID Docuement
536 * @param ego Identity whos DID Document is stored
537 */
538static void
539create_did_store (char *didd_str, struct GNUNET_IDENTITY_Ego *ego)
540{
541
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 {
551 record_data.data = didd_str;
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);
570 ret = 1;
571 return;
572 }
573}
574
575/**
576 * @brief Create a did ego lockup cb
577 *
578 * @param cls
579 * @param ego
580 */
581static void
582create_did_ego_lockup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
583{
584 struct GNUNET_IDENTITY_PublicKey pkey;
585 char *didd_str;
586
587 if (ego == NULL)
588 {
589 printf ("EGO not found\n");
590 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
591 ret = 1;
592 return;
593 }
594
595 GNUNET_IDENTITY_ego_get_public_key (ego, &pkey);
596
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 }
604
605 if (didd != NULL)
606 {
607 printf (
608 "DID Docuement is read from \"did-document\" argument (EXPERIMENTAL)\n");
609 didd_str = strdup (didd);
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
619 // Store the DID Document
620 create_did_store (didd_str, ego);
621
622 // Save DID Document String to GNS
623 free (didd_str);
624}
625
626/**
627 * @brief Create a did document - Create a new identity first
628 */
629static void
630create_did_document_ego_create_cb (void *cls,
631 const struct GNUNET_IDENTITY_PrivateKey *pk,
632 const char *emsg)
633{
634
635 if (emsg != NULL)
636 {
637 printf ("%s\n", emsg);
638 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
639 ret = 1;
640 return;
641 }
642
643 GNUNET_IDENTITY_ego_lookup (my_cfg,
644 egoname,
645 &create_did_ego_lockup_cb,
646 NULL);
647}
648
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
675/**
676 * @brief Replace a DID Docuemnt. Callback function after ego lockup
677 *
678 * @param cls
679 * @param ego
680 */
681static void
682replace_did_document_ego_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
683{
684 create_did_store (didd, ego);
685}
686
687/**
688 * @brief Replace a DID Document. Callback functiona after remove
689 *
690 * @param cls
691 */
692static void
693replace_did_document_remove_cb (void *cls)
694{
695 GNUNET_IDENTITY_ego_lookup (my_cfg,
696 egoname,
697 &replace_did_document_ego_lookup_cb,
698 NULL);
699}
700
701/**
702 * @brief Replace a DID Docuemnt
703 *
704 */
705static void
706replace_did_document ()
707{
708 if ((didd != NULL) && (expire != NULL))
709 {
710 remove_did_document (&replace_did_document_remove_cb, NULL);
711 }
712 else {
713 printf (
714 "Set the DID Document and expiration time argument to replace the DID Document\n");
715 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
716 ret = 1;
717 return;
718 }
719}
720
721static void
722post_ego_iteration (void *cls)
723{
724 if (1 == replace)
725 {
726 replace_did_document ();
727 }
728 else if (1 == get)
729 {
730 resolve_did_document ();
731 }
732 else if (1 == remove_did)
733 {
734 remove_did_document (NULL, NULL);
735 }
736 else if (1 == create)
737 {
738 create_did_document ();
739 }
740 else {
741 // No Argument found
742 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
743 return;
744 }
745}
746
747static void
748process_dids (void *cls, struct GNUNET_IDENTITY_Ego *ego,
749 void **ctx, const char*name)
750{
751 char *did_str;
752
753 if (ego == NULL)
754 {
755 if (1 == ego_exists)
756 {
757 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
758 return;
759 }
760 GNUNET_SCHEDULER_add_now (&post_ego_iteration, NULL);
761 return;
762 }
763 if (NULL == name)
764 return;
765 if ((1 == create) &&
766 (0 == strncmp (name, egoname, strlen (egoname))) &&
767 (1 != ego_exists))
768 {
769 fprintf(stderr, "%s already exists!\n", egoname);
770 ego_exists = 1;
771 return;
772 }
773 if (1 == show_all)
774 {
775 did_str = DID_ego_to_did (ego);
776 printf ("%s\n", did_str);
777 GNUNET_free (did_str);
778 return;
779 }
780 if (1 == show)
781 {
782 if (0 == strncmp (name, egoname, strlen (egoname)))
783 {
784 did_str = DID_ego_to_did (ego);
785 printf ("%s\n", did_str);
786 GNUNET_free (did_str);
787 return;
788 }
789 }
790}
791
792
793
794static void
795run (void *cls,
796 char *const *args,
797 const char *cfgfile,
798 const struct GNUNET_CONFIGURATION_Handle *c)
799{
800 gns_handle = GNUNET_GNS_connect (c);
801 namestore_handle = GNUNET_NAMESTORE_connect (c);
802 my_cfg = c;
803
804 // check if GNS_handle could connect
805 if (gns_handle == NULL)
806 {
807 ret = 1;
808 return;
809 }
810
811 // check if NAMESTORE_handle could connect
812 if (namestore_handle == NULL)
813 {
814 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
815 ret = 1;
816 return;
817 }
818
819 identity_handle = GNUNET_IDENTITY_connect (c, &process_dids, NULL);
820 if (identity_handle == NULL)
821 {
822 GNUNET_SCHEDULER_add_now (&cleanup, NULL);
823 ret = 1;
824 return;
825 }
826}
827
828int
829main (int argc, char *const argv[])
830{
831 struct GNUNET_GETOPT_CommandLineOption options[] = {
832 GNUNET_GETOPT_option_flag ('C',
833 "create",
834 gettext_noop (
835 "Create a DID Document and display its DID"),
836 &create),
837 GNUNET_GETOPT_option_flag ('g',
838 "get",
839 gettext_noop (
840 "Get the DID Document associated with the given DID"),
841 &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',
847 "remove",
848 gettext_noop (
849 "Remove the DID"),
850 &remove_did),
851 GNUNET_GETOPT_option_flag ('R',
852 "replace",
853 gettext_noop ("Replace the DID Document."),
854 &replace),
855 GNUNET_GETOPT_option_flag ('A',
856 "--show-all",
857 gettext_noop ("Replace the DID Document."),
858 &show_all),
859 GNUNET_GETOPT_option_string ('d',
860 "did",
861 "DID",
862 gettext_noop (
863 "The Decentralized Identity (DID)"),
864 &did),
865 GNUNET_GETOPT_option_string ('D',
866 "--did-document",
867 "JSON",
868 gettext_noop (
869 "The DID Document to store in GNUNET"),
870 &didd),
871 GNUNET_GETOPT_option_string ('e',
872 "ego",
873 "EGO",
874 gettext_noop ("The name of the EGO"),
875 &egoname),
876 GNUNET_GETOPT_option_string ('t',
877 "expiration-time",
878 "TIME",
879 gettext_noop (
880 "The time until the DID Document is going to expire (e.g. 5d)"),
881 &expire),
882 GNUNET_GETOPT_OPTION_END
883 };
884
885 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
886 argv,
887 "gnunet-did",
888 _ (
889 "Manage Decentralized Identities (DIDs)"),
890 options,
891 &run,
892 NULL))
893 return 1;
894 else
895 return ret;
896}