2 This file is part of GNUnet
3 (C) 2003, 2004, 2005, 2006, 2007, 2008, 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file util/pseudonym.c
22 * @brief helper functions
23 * @author Christian Grothoff
26 * - all cryptographic operations are currently NOT implemented and
27 * provided by stubs that merely pretend to work!
30 #include "gnunet_common.h"
31 #include "gnunet_container_lib.h"
32 #include "gnunet_disk_lib.h"
33 #include "gnunet_pseudonym_lib.h"
34 #include "gnunet_bio_lib.h"
37 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
39 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
42 * Name of the directory which stores meta data for pseudonym
44 #define PS_METADATA_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "metadata" DIR_SEPARATOR_STR
47 * Name of the directory which stores names for pseudonyms
49 #define PS_NAMES_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "names" DIR_SEPARATOR_STR
53 * Configuration section we use.
55 #define GNUNET_CLIENT_SERVICE_NAME "client"
58 /* ************************* Disk operations (pseudonym data mgmt) **************** */
61 * Registered callbacks for discovery of pseudonyms.
63 struct GNUNET_PSEUDONYM_DiscoveryHandle
66 * This is a doubly linked list.
68 struct GNUNET_PSEUDONYM_DiscoveryHandle *next;
71 * This is a doubly linked list.
73 struct GNUNET_PSEUDONYM_DiscoveryHandle *prev;
76 * Function to call each time a pseudonym is discovered.
78 GNUNET_PSEUDONYM_Iterator callback;
81 * Closure for callback.
88 * Head of the linked list of functions to call when
89 * new pseudonyms are added.
91 static struct GNUNET_PSEUDONYM_DiscoveryHandle *disco_head;
94 * Tail of the linked list of functions to call when
95 * new pseudonyms are added.
97 static struct GNUNET_PSEUDONYM_DiscoveryHandle *disco_tail;
101 * Internal notification about new tracked URI.
103 * @param pseudonym public key of the pseudonym
104 * @param md meta data to be written
105 * @param rating rating of pseudonym
108 internal_notify (const struct GNUNET_PseudonymIdentifier *pseudonym,
109 const struct GNUNET_CONTAINER_MetaData *md, int rating)
111 struct GNUNET_PSEUDONYM_DiscoveryHandle *pos;
113 for (pos = disco_head; NULL != pos; pos = pos->next)
114 pos->callback (pos->callback_cls, pseudonym, NULL, NULL, md, rating);
119 * Register callback to be invoked whenever we discover
121 * Will immediately call provided iterator callback for all
122 * already discovered pseudonyms.
124 * @param cfg configuration to use
125 * @param iterator iterator over pseudonym
126 * @param iterator_cls point to a closure
127 * @return registration handle
129 struct GNUNET_PSEUDONYM_DiscoveryHandle *
130 GNUNET_PSEUDONYM_discovery_callback_register (const struct
131 GNUNET_CONFIGURATION_Handle *cfg,
132 GNUNET_PSEUDONYM_Iterator iterator,
135 struct GNUNET_PSEUDONYM_DiscoveryHandle *dh;
137 dh = GNUNET_malloc (sizeof (struct GNUNET_PSEUDONYM_DiscoveryHandle));
138 dh->callback = iterator;
139 dh->callback_cls = iterator_cls;
140 GNUNET_CONTAINER_DLL_insert (disco_head, disco_tail, dh);
141 GNUNET_PSEUDONYM_list_all (cfg, iterator, iterator_cls);
147 * Unregister pseudonym discovery callback.
149 * @param dh registration to unregister
152 GNUNET_PSEUDONYM_discovery_callback_unregister (struct GNUNET_PSEUDONYM_DiscoveryHandle *dh)
154 GNUNET_CONTAINER_DLL_remove (disco_head, disco_tail, dh);
160 * Get the filename (or directory name) for the given
161 * pseudonym identifier and directory prefix.
163 * @param cfg configuration to use
164 * @param prefix path components to append to the private directory name
165 * @param pseudonym the pseudonym, can be NULL
166 * @return filename of the pseudonym (if pseudonym != NULL) or directory with the data (if pseudonym == NULL)
169 get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
171 const struct GNUNET_PseudonymIdentifier *pseudonym)
173 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
174 struct GNUNET_HashCode psid;
176 if (NULL != pseudonym)
178 GNUNET_CRYPTO_hash (pseudonym,
179 sizeof (struct GNUNET_PseudonymIdentifier),
181 GNUNET_CRYPTO_hash_to_enc (&psid, &enc);
183 return GNUNET_DISK_get_home_filename (cfg,
184 GNUNET_CLIENT_SERVICE_NAME, prefix,
187 : (const char *) &enc,
193 * Get the filename (or directory name) for the given
194 * hash code and directory prefix.
196 * @param cfg configuration to use
197 * @param prefix path components to append to the private directory name
198 * @param hc some hash code
199 * @return filename of the pseudonym (if hc != NULL) or directory with the data (if hc == NULL)
202 get_data_filename_hash (const struct GNUNET_CONFIGURATION_Handle *cfg,
204 const struct GNUNET_HashCode *hc)
206 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
209 GNUNET_CRYPTO_hash_to_enc (hc, &enc);
210 return GNUNET_DISK_get_home_filename (cfg,
211 GNUNET_CLIENT_SERVICE_NAME, prefix,
214 : (const char *) &enc,
220 * Set the pseudonym metadata, rank and name.
221 * Writes the pseudonym infomation into a file
223 * @param cfg overall configuration
224 * @param nsid id of the pseudonym
225 * @param name name to set. Must be the non-unique version of it.
226 * May be NULL, in which case it erases pseudonym's name!
227 * @param md metadata to set
228 * May be NULL, in which case it erases pseudonym's metadata!
229 * @param rank rank to assign
230 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
233 GNUNET_PSEUDONYM_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
234 const struct GNUNET_PseudonymIdentifier *pseudonym,
236 const struct GNUNET_CONTAINER_MetaData *md,
240 struct GNUNET_BIO_WriteHandle *fileW;
242 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
243 if (NULL == (fileW = GNUNET_BIO_write_open (fn)))
246 return GNUNET_SYSERR;
248 if ((GNUNET_OK != GNUNET_BIO_write (fileW, pseudonym,
249 sizeof (struct GNUNET_PseudonymIdentifier))) ||
250 (GNUNET_OK != GNUNET_BIO_write_int32 (fileW, rank)) ||
251 (GNUNET_OK != GNUNET_BIO_write_string (fileW, name)) ||
252 (GNUNET_OK != GNUNET_BIO_write_meta_data (fileW, md)))
254 (void) GNUNET_BIO_write_close (fileW);
255 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
257 return GNUNET_SYSERR;
259 if (GNUNET_OK != GNUNET_BIO_write_close (fileW))
261 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
263 return GNUNET_SYSERR;
266 /* create entry for pseudonym name in names */
268 GNUNET_free_non_null (GNUNET_PSEUDONYM_name_uniquify (cfg, pseudonym,
275 * Read pseudonym infomation from a file
277 * @param cfg configuration to use
278 * @param nsid hash code of a pseudonym
279 * @param meta meta data to be read from a file
280 * @param rank rank of a pseudonym
281 * @param ns_name name of a pseudonym
282 * @return GNUNET_OK on success, GNUNET_SYSERR on error
285 read_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
286 const struct GNUNET_PseudonymIdentifier *pseudonym,
287 struct GNUNET_CONTAINER_MetaData **meta,
291 struct GNUNET_PseudonymIdentifier pd;
294 struct GNUNET_BIO_ReadHandle *fileR;
296 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
298 GNUNET_DISK_file_test (fn))
301 return GNUNET_SYSERR;
303 if (NULL == (fileR = GNUNET_BIO_read_open (fn)))
306 return GNUNET_SYSERR;
310 if ( (GNUNET_OK != GNUNET_BIO_read (fileR, "pseudonym", &pd, sizeof (pd))) ||
311 (0 != memcmp (&pd, pseudonym, sizeof (pd))) ||
312 (GNUNET_OK != GNUNET_BIO_read_int32 (fileR, rank)) ||
314 GNUNET_BIO_read_string (fileR, "Read string error!", ns_name, 200)) ||
316 GNUNET_BIO_read_meta_data (fileR, "Read meta data error!", meta)) )
318 (void) GNUNET_BIO_read_close (fileR, &emsg);
319 GNUNET_free_non_null (emsg);
320 GNUNET_free_non_null (*ns_name);
322 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
324 return GNUNET_SYSERR;
326 if (GNUNET_OK != GNUNET_BIO_read_close (fileR, &emsg))
328 LOG (GNUNET_ERROR_TYPE_WARNING,
329 _("Failed to parse metadata about pseudonym from file `%s': %s\n"), fn,
331 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
332 GNUNET_CONTAINER_meta_data_destroy (*meta);
334 GNUNET_free_non_null (*ns_name);
336 GNUNET_free_non_null (emsg);
338 return GNUNET_SYSERR;
346 * Return unique variant of the namespace name. Use it after
347 * GNUNET_PSEUDONYM_get_info() to make sure that name is unique.
349 * @param cfg configuration
350 * @param pseudonym public key of the pseudonym
351 * @param name name to uniquify
352 * @param suffix if not NULL, filled with the suffix value
353 * @return NULL on failure (should never happen), name on success.
354 * Free the name with GNUNET_free().
357 GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg,
358 const struct GNUNET_PseudonymIdentifier *pseudonym,
360 unsigned int *suffix)
362 struct GNUNET_HashCode nh;
363 struct GNUNET_PseudonymIdentifier pi;
366 struct GNUNET_DISK_FileHandle *fh;
372 GNUNET_CRYPTO_hash (name, strlen (name), &nh);
373 fn = get_data_filename_hash (cfg, PS_NAMES_DIR, &nh);
375 if (0 == STAT (fn, &sbuf))
376 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES));
377 fh = GNUNET_DISK_file_open (fn,
378 GNUNET_DISK_OPEN_CREATE |
379 GNUNET_DISK_OPEN_READWRITE,
380 GNUNET_DISK_PERM_USER_READ |
381 GNUNET_DISK_PERM_USER_WRITE);
384 while ((len >= sizeof (struct GNUNET_PseudonymIdentifier)) &&
385 (sizeof (struct GNUNET_PseudonymIdentifier) ==
386 GNUNET_DISK_file_read (fh, &pi, sizeof (struct GNUNET_PseudonymIdentifier))))
388 if (0 == memcmp (&pi, pseudonym, sizeof (struct GNUNET_PseudonymIdentifier)))
394 len -= sizeof (struct GNUNET_HashCode);
399 if (sizeof (struct GNUNET_PseudonymIdentifier) !=
400 GNUNET_DISK_file_write (fh, pseudonym, sizeof (struct GNUNET_PseudonymIdentifier)))
401 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn);
403 GNUNET_DISK_file_close (fh);
404 ret = GNUNET_malloc (strlen (name) + 32);
405 GNUNET_snprintf (ret, strlen (name) + 32, "%s-%u", name, idx);
414 * Get namespace name, metadata and rank
415 * This is a wrapper around internal read_info() call, and ensures that
416 * returned data is not invalid (not NULL).
418 * @param cfg configuration
419 * @param pseudonym public key of the pseudonym
420 * @param ret_meta a location to store metadata pointer. NULL, if metadata
421 * is not needed. Destroy with GNUNET_CONTAINER_meta_data_destroy().
422 * @param ret_rank a location to store rank. NULL, if rank not needed.
423 * @param ret_name a location to store human-readable name. Name is not unique.
424 * NULL, if name is not needed. Free with GNUNET_free().
425 * @param name_is_a_dup is set to GNUNET_YES, if ret_name was filled with
426 * a duplicate of a "no-name" placeholder
427 * @return GNUNET_OK on success. GNUENT_SYSERR if the data was
428 * unobtainable (in that case ret_* are filled with placeholders -
429 * empty metadata container, rank -1 and a "no-name" name).
432 GNUNET_PSEUDONYM_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
433 const struct GNUNET_PseudonymIdentifier *pseudonym,
434 struct GNUNET_CONTAINER_MetaData **ret_meta,
439 struct GNUNET_CONTAINER_MetaData *meta;
445 if (GNUNET_OK == read_info (cfg, pseudonym, &meta, &rank, &name))
447 if ((meta != NULL) && (name == NULL))
449 GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
450 EXTRACTOR_METATYPE_TITLE,
451 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
452 EXTRACTOR_METATYPE_FILENAME,
453 EXTRACTOR_METATYPE_DESCRIPTION,
454 EXTRACTOR_METATYPE_SUBJECT,
455 EXTRACTOR_METATYPE_PUBLISHER,
456 EXTRACTOR_METATYPE_AUTHOR_NAME,
457 EXTRACTOR_METATYPE_COMMENT,
458 EXTRACTOR_METATYPE_SUMMARY,
460 if (ret_name != NULL)
464 name = GNUNET_strdup (_("no-name"));
465 if (name_is_a_dup != NULL)
466 *name_is_a_dup = GNUNET_YES;
468 else if (name_is_a_dup != NULL)
469 *name_is_a_dup = GNUNET_NO;
472 else if (name != NULL)
475 if (ret_meta != NULL)
478 meta = GNUNET_CONTAINER_meta_data_create ();
481 else if (meta != NULL)
482 GNUNET_CONTAINER_meta_data_destroy (meta);
484 if (ret_rank != NULL)
489 if (ret_name != NULL)
490 *ret_name = GNUNET_strdup (_("no-name"));
491 if (ret_meta != NULL)
492 *ret_meta = GNUNET_CONTAINER_meta_data_create ();
493 if (ret_rank != NULL)
495 if (name_is_a_dup != NULL)
496 *name_is_a_dup = GNUNET_YES;
497 return GNUNET_SYSERR;
502 * Get the namespace ID belonging to the given namespace name.
504 * @param cfg configuration to use
505 * @param ns_uname unique (!) human-readable name for the namespace
506 * @param pseudonym set to public key of pseudonym based on 'ns_uname'
507 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
510 GNUNET_PSEUDONYM_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg,
511 const char *ns_uname,
512 struct GNUNET_PseudonymIdentifier *pseudonym)
518 struct GNUNET_HashCode nh;
520 struct GNUNET_DISK_FileHandle *fh;
523 slen = strlen (ns_uname);
524 while ((slen > 0) && (1 != SSCANF (&ns_uname[slen - 1], "-%u", &idx)))
527 return GNUNET_SYSERR;
528 name = GNUNET_strdup (ns_uname);
529 name[slen - 1] = '\0';
531 GNUNET_CRYPTO_hash (name, strlen (name), &nh);
533 fn = get_data_filename_hash (cfg, PS_NAMES_DIR, &nh);
535 if ((GNUNET_OK != GNUNET_DISK_file_test (fn) ||
536 (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) ||
537 ((idx + 1) * sizeof (struct GNUNET_PseudonymIdentifier) > len))
540 return GNUNET_SYSERR;
542 fh = GNUNET_DISK_file_open (fn,
543 GNUNET_DISK_OPEN_CREATE |
544 GNUNET_DISK_OPEN_READWRITE,
545 GNUNET_DISK_PERM_USER_READ |
546 GNUNET_DISK_PERM_USER_WRITE);
549 GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_PseudonymIdentifier),
550 GNUNET_DISK_SEEK_SET))
552 GNUNET_DISK_file_close (fh);
553 return GNUNET_SYSERR;
555 if (sizeof (struct GNUNET_PseudonymIdentifier) !=
556 GNUNET_DISK_file_read (fh, pseudonym, sizeof (struct GNUNET_PseudonymIdentifier)))
558 GNUNET_DISK_file_close (fh);
559 return GNUNET_SYSERR;
561 GNUNET_DISK_file_close (fh);
568 * struct used to list the pseudonym
570 struct ListPseudonymClosure
574 * iterator over pseudonym
576 GNUNET_PSEUDONYM_Iterator iterator;
579 * Closure for iterator.
584 * Configuration to use.
586 const struct GNUNET_CONFIGURATION_Handle *cfg;
592 * Helper function to list all available pseudonyms
594 * @param cls point to a struct ListPseudonymClosure
595 * @param fullname name of pseudonym
598 list_pseudonym_helper (void *cls, const char *fullname)
600 struct ListPseudonymClosure *lpc = cls;
601 struct GNUNET_PseudonymIdentifier pd;
603 struct GNUNET_BIO_ReadHandle *fileR;
606 struct GNUNET_CONTAINER_MetaData *meta;
610 if (NULL == (fileR = GNUNET_BIO_read_open (fullname)))
611 return GNUNET_SYSERR;
614 if ( (GNUNET_OK != GNUNET_BIO_read (fileR, "pseudonym", &pd, sizeof (pd))) ||
615 (GNUNET_OK != GNUNET_BIO_read_int32 (fileR, &rank)) ||
617 GNUNET_BIO_read_string (fileR, "Read string error!", &ns_name, 200)) ||
619 GNUNET_BIO_read_meta_data (fileR, "Read meta data error!", &meta)) )
621 (void) GNUNET_BIO_read_close (fileR, &emsg);
622 GNUNET_free_non_null (emsg);
623 GNUNET_free_non_null (ns_name);
624 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fullname));
625 return GNUNET_SYSERR;
628 ns_name = GNUNET_strdup (_("no-name"));
629 if (GNUNET_OK != GNUNET_BIO_read_close (fileR, &emsg))
631 LOG (GNUNET_ERROR_TYPE_WARNING,
632 _("Failed to parse metadata about pseudonym from file `%s': %s\n"), fullname,
634 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fullname));
635 GNUNET_CONTAINER_meta_data_destroy (meta);
636 GNUNET_free (ns_name);
637 GNUNET_free_non_null (emsg);
638 return GNUNET_SYSERR;
641 name_unique = GNUNET_PSEUDONYM_name_uniquify (lpc->cfg, &pd, ns_name, NULL);
642 if (NULL != lpc->iterator)
643 ret = lpc->iterator (lpc->iterator_cls, &pd, ns_name, name_unique, meta, rank);
644 GNUNET_free (ns_name);
645 GNUNET_free_non_null (name_unique);
646 GNUNET_CONTAINER_meta_data_destroy (meta);
652 * List all available pseudonyms.
654 * @param cfg overall configuration
655 * @param iterator function to call for each pseudonym
656 * @param iterator_cls closure for iterator
657 * @return number of pseudonyms found
660 GNUNET_PSEUDONYM_list_all (const struct GNUNET_CONFIGURATION_Handle *cfg,
661 GNUNET_PSEUDONYM_Iterator iterator,
664 struct ListPseudonymClosure cls;
668 cls.iterator = iterator;
669 cls.iterator_cls = iterator_cls;
671 fn = get_data_filename (cfg, PS_METADATA_DIR, NULL);
672 GNUNET_assert (fn != NULL);
673 GNUNET_DISK_directory_create (fn);
674 ret = GNUNET_DISK_directory_scan (fn, &list_pseudonym_helper, &cls);
681 * Change the rank of a pseudonym.
683 * @param cfg overall configuration
684 * @param pseudonym the pseudonym
685 * @param delta by how much should the rating be changed?
686 * @return new rating of the pseudonym
689 GNUNET_PSEUDONYM_rank (const struct GNUNET_CONFIGURATION_Handle *cfg,
690 const struct GNUNET_PseudonymIdentifier *pseudonym,
693 struct GNUNET_CONTAINER_MetaData *meta;
699 ret = read_info (cfg, pseudonym, &meta, &rank, &name);
700 if (ret == GNUNET_SYSERR)
703 meta = GNUNET_CONTAINER_meta_data_create ();
706 GNUNET_PSEUDONYM_set_info (cfg, pseudonym, name, meta, rank);
707 GNUNET_CONTAINER_meta_data_destroy (meta);
708 GNUNET_free_non_null (name);
714 * Add a pseudonym to the set of known pseudonyms.
715 * For all pseudonym advertisements that we discover
716 * FS should automatically call this function.
718 * @param cfg overall configuration
719 * @param pseudonym the pseudonym to add
720 * @param meta metadata for the pseudonym
721 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
724 GNUNET_PSEUDONYM_add (const struct GNUNET_CONFIGURATION_Handle *cfg,
725 const struct GNUNET_PseudonymIdentifier *pseudonym,
726 const struct GNUNET_CONTAINER_MetaData *meta)
730 struct GNUNET_CONTAINER_MetaData *old;
736 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
737 GNUNET_assert (fn != NULL);
739 if ((0 == STAT (fn, &sbuf)) &&
740 (GNUNET_OK == read_info (cfg, pseudonym, &old, &rank, &name)))
742 GNUNET_CONTAINER_meta_data_merge (old, meta);
743 ret = GNUNET_PSEUDONYM_set_info (cfg, pseudonym, name, old, rank);
744 GNUNET_CONTAINER_meta_data_destroy (old);
745 GNUNET_free_non_null (name);
749 ret = GNUNET_PSEUDONYM_set_info (cfg, pseudonym, NULL, meta, rank);
752 internal_notify (pseudonym, meta, rank);
757 /* ***************************** cryptographic operations ************************* */
760 * Handle for a pseudonym (private key).
762 struct GNUNET_PseudonymHandle
772 * Create a pseudonym.
774 * @param filename name of the file to use for storage, NULL for in-memory only
775 * @return handle to the private key of the pseudonym
777 struct GNUNET_PseudonymHandle *
778 GNUNET_PSEUDONYM_create (const char *filename)
780 struct GNUNET_PseudonymHandle *ph;
783 ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle));
784 if (NULL != filename)
786 ret = GNUNET_DISK_fn_read (filename, ph,
787 sizeof (struct GNUNET_PseudonymHandle));
788 if (sizeof (struct GNUNET_PseudonymHandle) == ret)
791 GNUNET_break (0); // not implemented...
792 gcry_randomize (ph, sizeof (struct GNUNET_PseudonymHandle),
794 if (NULL != filename)
796 ret = GNUNET_DISK_fn_write (filename, ph, sizeof (struct GNUNET_PseudonymHandle),
797 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
798 if (sizeof (struct GNUNET_PseudonymHandle) != ret)
809 * Create a pseudonym, from a file that must already exist.
811 * @param filename name of the file to use for storage, NULL for in-memory only
812 * @return handle to the private key of the pseudonym
814 struct GNUNET_PseudonymHandle *
815 GNUNET_PSEUDONYM_create_from_existing_file (const char *filename)
817 struct GNUNET_PseudonymHandle *ph;
820 ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle));
821 ret = GNUNET_DISK_fn_read (filename, ph,
822 sizeof (struct GNUNET_PseudonymHandle));
823 if (sizeof (struct GNUNET_PseudonymHandle) == ret)
831 * Get the handle for the 'anonymous' pseudonym shared by all users.
832 * That pseudonym uses a fixed 'secret' for the private key; this
833 * construction is useful to make anonymous and pseudonymous APIs
834 * (and packets) indistinguishable on the network. See #2564.
836 * @return handle to the (non-secret) private key of the 'anonymous' pseudonym
838 struct GNUNET_PseudonymHandle *
839 GNUNET_PSEUDONYM_get_anonymous_pseudonym_handle ()
841 struct GNUNET_PseudonymHandle *ph;
843 ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle));
850 * Destroy a pseudonym handle. Does NOT remove the private key from
853 * @param ph pseudonym handle to destroy
856 GNUNET_PSEUDONYM_destroy (struct GNUNET_PseudonymHandle *ph)
863 * Cryptographically sign some data with the pseudonym.
865 * @param ph private key used for signing (corresponds to 'x' in #2564)
866 * @param purpose data to sign
867 * @param seed hash of the plaintext of the data that we are signing,
868 * used for deterministic PRNG for anonymous signing;
869 * corresponds to 'k' in section 2.7 of #2564
870 * @param signing_key modifier to apply to the private key for signing;
871 * corresponds to 'h' in section 2.3 of #2564.
872 * @param signature where to store the signature
875 GNUNET_PSEUDONYM_sign (struct GNUNET_PseudonymHandle *ph,
876 const struct GNUNET_PseudonymSignaturePurpose *purpose,
877 const struct GNUNET_HashCode *seed,
878 const struct GNUNET_HashCode *signing_key,
879 struct GNUNET_PseudonymSignature *signature)
881 memset (signature, 0, sizeof (struct GNUNET_PseudonymSignature));
887 * Given a pseudonym and a signing key, derive the corresponding public
888 * key that would be used to verify the resulting signature.
890 * @param pseudonym the public key (g^x)
891 * @param signing_key input to derive 'h' (see section 2.4 of #2564)
892 * @param verification_key resulting public key to verify the signature
893 * created from the 'ph' of 'pseudonym' and the 'signing_key';
894 * the value stored here can then be given to GNUNET_PSEUDONYM_verify.
897 GNUNET_PSEUDONYM_derive_verification_key (struct GNUNET_PseudonymIdentifier *pseudonym,
898 const struct GNUNET_HashCode *signing_key,
899 struct GNUNET_PseudonymIdentifier *verification_key)
901 struct GNUNET_HashCode hc;
902 struct GNUNET_HashCode x;
905 GNUNET_CRYPTO_hash (pseudonym, sizeof (*pseudonym), &hc);
906 GNUNET_CRYPTO_hash_xor (&hc, signing_key, &x);
907 memset (verification_key, 0, sizeof (struct GNUNET_PseudonymIdentifier));
908 memcpy (verification_key, &x, GNUNET_MIN (sizeof (x), sizeof (*verification_key)));
913 * Verify a signature made with a pseudonym.
915 * @param purpose data that was signed
916 * @param signature signature to verify
917 * @param verification_key public key to use for checking the signature;
918 * corresponds to 'g^(x+h)' in section 2.4 of #2564.
919 * @return GNUNET_OK on success (signature valid, 'pseudonym' set),
920 * GNUNET_SYSERR if the signature is invalid
923 GNUNET_PSEUDONYM_verify (const struct GNUNET_PseudonymSignaturePurpose *purpose,
924 const struct GNUNET_PseudonymSignature *signature,
925 const struct GNUNET_PseudonymIdentifier *verification_key)
933 * Get the identifier (public key) of a pseudonym.
935 * @param ph pseudonym handle with the private key
936 * @param pseudonym pseudonym identifier (set based on 'ph')
939 GNUNET_PSEUDONYM_get_identifier (struct GNUNET_PseudonymHandle *ph,
940 struct GNUNET_PseudonymIdentifier *pseudonym)
943 memcpy (pseudonym, ph,
944 GNUNET_MIN (sizeof (struct GNUNET_PseudonymIdentifier),
950 * Remove pseudonym from the set of known pseudonyms.
952 * @param cfg overall configuration
953 * @param id the pseudonym identifier
954 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
957 GNUNET_PSEUDONYM_remove (const struct GNUNET_CONFIGURATION_Handle *cfg,
958 const struct GNUNET_PseudonymIdentifier *id)
963 result = GNUNET_SYSERR;
964 fn = get_data_filename (cfg, PS_METADATA_DIR, id);
967 result = UNLINK (fn);
970 return (GNUNET_OK == result ? GNUNET_OK : GNUNET_SYSERR);
973 /* end of pseudonym.c */