summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--po/POTFILES.in1
-rw-r--r--po/de.po123
-rw-r--r--po/es.po123
-rw-r--r--po/sv.po123
-rw-r--r--po/vi.po123
-rw-r--r--po/zh_CN.po123
-rw-r--r--src/consensus/consensus.h9
-rw-r--r--src/consensus/consensus_api.c6
-rw-r--r--src/consensus/gnunet-consensus-profiler.c2
-rw-r--r--src/consensus/gnunet-service-consensus.c4
-rw-r--r--src/include/gnunet_common.h11
-rw-r--r--src/include/gnunet_consensus_service.h8
-rw-r--r--src/include/gnunet_secretsharing_service.h56
-rw-r--r--src/include/gnunet_signatures.h15
-rw-r--r--src/secretsharing/Makefile.am12
-rwxr-xr-xsrc/secretsharing/gnunet-secretsharing-profiler.c316
-rw-r--r--src/secretsharing/gnunet-service-secretsharing.c772
-rw-r--r--src/secretsharing/secretsharing.h121
-rw-r--r--src/secretsharing/secretsharing_api.c125
-rw-r--r--src/secretsharing/secretsharing_protocol.h45
-rw-r--r--src/secretsharing/test_secretsharing.conf36
-rw-r--r--src/secretsharing/test_secretsharing_sig.c45
22 files changed, 1724 insertions, 475 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 063c1573a..241ee27d1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -260,6 +260,7 @@ src/statistics/statistics_api.c
src/template/gnunet-service-template.c
src/template/gnunet-template.c
src/testbed/gnunet-daemon-testbed-blacklist.c
+src/testbed/gnunet-daemon-testbed-underlay.c
src/testbed/gnunet-helper-testbed.c
src/testbed/gnunet_mpi_test.c
src/testbed/gnunet-service-test-barriers.c
diff --git a/po/de.po b/po/de.po
index a6a347468..0e474a06a 100644
--- a/po/de.po
+++ b/po/de.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: GNUnet 0.7.0b\n"
"Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2013-12-24 21:07+0100\n"
+"POT-Creation-Date: 2014-01-05 13:20+0100\n"
"PO-Revision-Date: 2006-03-17 21:37+0100\n"
"Last-Translator: Nils Durner <durner@gnunet.org>\n"
"Language-Team: German <de@li.org>\n"
@@ -390,17 +390,17 @@ msgid ""
"%llu\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2180
+#: src/ats/gnunet-service-ats_addresses.c:2184
#, c-format
msgid "Initializing solver `%s '`%s'\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2183
+#: src/ats/gnunet-service-ats_addresses.c:2187
#, fuzzy, c-format
msgid "Failed to initialize solver `%s'!\n"
msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n"
-#: src/ats/gnunet-service-ats_addresses.c:2206
+#: src/ats/gnunet-service-ats_addresses.c:2210
#, fuzzy
msgid "Failed to initialize solver!\n"
msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n"
@@ -4783,45 +4783,49 @@ msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':"
msgid "Failed to create directory `%s' for storing egos\n"
msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n"
-#: src/mesh/gnunet-mesh.c:300
+#: src/mesh/gnunet-mesh.c:342
#, fuzzy, c-format
msgid "Invalid target `%s'\n"
msgstr "Ungültiger Parameter: `%s'\n"
-#: src/mesh/gnunet-mesh.c:434
+#: src/mesh/gnunet-mesh.c:503
#, fuzzy, c-format
msgid "Invalid tunnel owner `%s'\n"
msgstr "Ungültiger Parameter: `%s'\n"
-#: src/mesh/gnunet-mesh.c:499
+#: src/mesh/gnunet-mesh.c:568
msgid "You must NOT give a TARGET when using options\n"
msgstr ""
-#: src/mesh/gnunet-mesh.c:576
+#: src/mesh/gnunet-mesh.c:645
#, fuzzy
msgid "provide information about a particular channel"
msgstr "Informationen über andere GNUnet Knoten ausgeben."
-#: src/mesh/gnunet-mesh.c:579
+#: src/mesh/gnunet-mesh.c:648
#, fuzzy
msgid "provide information about a particular connection"
msgstr "Informationen über andere GNUnet Knoten ausgeben."
-#: src/mesh/gnunet-mesh.c:582
+#: src/mesh/gnunet-mesh.c:651
+msgid "activate echo mode"
+msgstr ""
+
+#: src/mesh/gnunet-mesh.c:654
#, fuzzy
msgid "provide information about all tunnels"
msgstr "Informationen über andere GNUnet Knoten ausgeben."
-#: src/mesh/gnunet-mesh.c:585
+#: src/mesh/gnunet-mesh.c:657
#, fuzzy
msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED"
msgstr "Informationen über andere GNUnet Knoten ausgeben."
-#: src/mesh/gnunet-mesh.c:588
+#: src/mesh/gnunet-mesh.c:660
msgid "port to listen to (default; 0)"
msgstr ""
-#: src/mesh/gnunet-mesh.c:591
+#: src/mesh/gnunet-mesh.c:663
#, fuzzy
msgid "provide information about a particular tunnel"
msgstr "Informationen über andere GNUnet Knoten ausgeben."
@@ -6071,7 +6075,7 @@ msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
msgid "Failed to send a message to the scalarproduct service\n"
msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n"
-#: src/set/gnunet-service-set.c:1403
+#: src/set/gnunet-service-set.c:1416
#, fuzzy
msgid "Could not connect to mesh service\n"
msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n"
@@ -6211,6 +6215,16 @@ msgid ""
"deployments"
msgstr ""
+#: src/testbed/gnunet-daemon-testbed-underlay.c:300 src/testing/testing.c:293
+#: src/util/gnunet-ecc.c:217
+#, c-format
+msgid "Incorrect hostkey file format: %s\n"
+msgstr ""
+
+#: src/testbed/gnunet-daemon-testbed-underlay.c:553
+msgid "Daemon to restrict underlay network in testbed deployments"
+msgstr ""
+
#: src/testbed/gnunet-service-testbed_cpustatus.c:727
#, c-format
msgid ""
@@ -6433,11 +6447,6 @@ msgstr ""
msgid "Hostkeys file not found: %s\n"
msgstr ""
-#: src/testing/testing.c:293 src/util/gnunet-ecc.c:217
-#, c-format
-msgid "Incorrect hostkey file format: %s\n"
-msgstr ""
-
#: src/testing/testing.c:716
#, fuzzy, c-format
msgid "Key number %u does not exist\n"
@@ -7325,44 +7334,44 @@ msgid "Unexpected address length: %u bytes\n"
msgstr ""
#: src/transport/plugin_transport_tcp.c:799
-#: src/transport/plugin_transport_tcp.c:979
+#: src/transport/plugin_transport_tcp.c:980
#: src/transport/plugin_transport_tcp.c:2120
#: src/transport/plugin_transport_tcp.c:2723
#, fuzzy
msgid "# TCP sessions active"
msgstr "# Sitzungsschlüssel akzeptiert"
-#: src/transport/plugin_transport_tcp.c:835
-#: src/transport/plugin_transport_tcp.c:972
-#: src/transport/plugin_transport_tcp.c:1061
-#: src/transport/plugin_transport_tcp.c:1111
-#: src/transport/plugin_transport_tcp.c:1290
-#: src/transport/plugin_transport_tcp.c:1309
+#: src/transport/plugin_transport_tcp.c:836
+#: src/transport/plugin_transport_tcp.c:973
+#: src/transport/plugin_transport_tcp.c:1062
+#: src/transport/plugin_transport_tcp.c:1112
+#: src/transport/plugin_transport_tcp.c:1291
+#: src/transport/plugin_transport_tcp.c:1310
#, fuzzy
msgid "# bytes currently in TCP buffers"
msgstr "# Bytes gesendet über TCP"
-#: src/transport/plugin_transport_tcp.c:839
+#: src/transport/plugin_transport_tcp.c:840
#, fuzzy
msgid "# bytes discarded by TCP (disconnect)"
msgstr "# Bytes verworfen von TCP (ausgehend)"
-#: src/transport/plugin_transport_tcp.c:1065
+#: src/transport/plugin_transport_tcp.c:1066
#, fuzzy
msgid "# bytes discarded by TCP (timeout)"
msgstr "# Bytes verworfen von TCP (ausgehend)"
-#: src/transport/plugin_transport_tcp.c:1114
+#: src/transport/plugin_transport_tcp.c:1115
#, fuzzy
msgid "# bytes transmitted via TCP"
msgstr "# Bytes des Typs %d übertragen"
-#: src/transport/plugin_transport_tcp.c:1263
+#: src/transport/plugin_transport_tcp.c:1264
#, c-format
msgid "Trying to send with invalid session %p\n"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:1520
+#: src/transport/plugin_transport_tcp.c:1521
#: src/transport/plugin_transport_udp.c:1488
msgid "# requests to create session with invalid address"
msgstr ""
@@ -8288,114 +8297,114 @@ msgstr "Aufruf von `%s' gibt %d zurück.\n"
msgid "b"
msgstr "b"
-#: src/util/strings.c:452
+#: src/util/strings.c:444
#, c-format
msgid "Character sets requested were `%s'->`%s'\n"
msgstr ""
-#: src/util/strings.c:580
+#: src/util/strings.c:572
msgid "Failed to expand `$HOME': environment variable `HOME' not set"
msgstr ""
-#: src/util/strings.c:677
+#: src/util/strings.c:669
msgid "µs"
msgstr ""
-#: src/util/strings.c:681
+#: src/util/strings.c:673
msgid "forever"
msgstr ""
-#: src/util/strings.c:683
+#: src/util/strings.c:675
msgid "0 ms"
msgstr ""
-#: src/util/strings.c:689
+#: src/util/strings.c:681
msgid "ms"
msgstr "ms"
-#: src/util/strings.c:695
+#: src/util/strings.c:687
msgid "s"
msgstr "s"
-#: src/util/strings.c:701
+#: src/util/strings.c:693
msgid "m"
msgstr "m"
-#: src/util/strings.c:707
+#: src/util/strings.c:699
msgid "h"
msgstr "h"
-#: src/util/strings.c:714
+#: src/util/strings.c:706
#, fuzzy
msgid "day"
msgstr " Tage"
-#: src/util/strings.c:716
+#: src/util/strings.c:708
#, fuzzy
msgid "days"
msgstr " Tage"
-#: src/util/strings.c:745
+#: src/util/strings.c:737
msgid "end of time"
msgstr ""
-#: src/util/strings.c:1178
+#: src/util/strings.c:1170
msgid "IPv6 address did not start with `['\n"
msgstr ""
-#: src/util/strings.c:1186
+#: src/util/strings.c:1178
msgid "IPv6 address did contain ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1192
+#: src/util/strings.c:1184
msgid "IPv6 address did contain ']' before ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1199
+#: src/util/strings.c:1191
msgid "IPv6 address did contain a valid port number after the last ':'\n"
msgstr ""
-#: src/util/strings.c:1208
+#: src/util/strings.c:1200
#, fuzzy, c-format
msgid "Invalid IPv6 address `%s': %s\n"
msgstr "Ungültiger Parameter: `%s'\n"
-#: src/util/strings.c:1414 src/util/strings.c:1430
+#: src/util/strings.c:1406 src/util/strings.c:1422
msgid "Port not in range\n"
msgstr ""
-#: src/util/strings.c:1439
+#: src/util/strings.c:1431
#, fuzzy, c-format
msgid "Malformed port policy `%s'\n"
msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n"
-#: src/util/strings.c:1522 src/util/strings.c:1553 src/util/strings.c:1601
-#: src/util/strings.c:1622
+#: src/util/strings.c:1514 src/util/strings.c:1545 src/util/strings.c:1593
+#: src/util/strings.c:1614
#, c-format
msgid "Invalid format for IP: `%s'\n"
msgstr "Ungültiges Format für IP: `%s'\n"
-#: src/util/strings.c:1579
+#: src/util/strings.c:1571
#, c-format
msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
msgstr "Ungültige Netzwerk Notation ('/%d ist nicht gültig in IPv4 CIDR)."
-#: src/util/strings.c:1631
+#: src/util/strings.c:1623
#, fuzzy, c-format
msgid "Invalid format: `%s'\n"
msgstr "Ungültiger Parameter: `%s'\n"
-#: src/util/strings.c:1683
+#: src/util/strings.c:1675
#, c-format
msgid "Invalid network notation (does not end with ';': `%s')\n"
msgstr "Ungültige Netzwerk Notation (endet nicht mit ';': `%s')\n"
-#: src/util/strings.c:1733
+#: src/util/strings.c:1725
#, fuzzy, c-format
msgid "Wrong format `%s' for netmask\n"
msgstr "Falsches Format `%s' für Netzmaske: %s\n"
-#: src/util/strings.c:1764
+#: src/util/strings.c:1756
#, fuzzy, c-format
msgid "Wrong format `%s' for network\n"
msgstr "Falsches Format `%s' für Netzwerk: %s\n"
diff --git a/po/es.po b/po/es.po
index 52c025a55..218970899 100644
--- a/po/es.po
+++ b/po/es.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gnunet 0.9.5a\n"
"Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2013-12-24 21:07+0100\n"
+"POT-Creation-Date: 2014-01-05 13:20+0100\n"
"PO-Revision-Date: 2013-02-23 17:50+0100\n"
"Last-Translator: Miguel Ángel Arruga Vivas <rosen644835@gmail.com>\n"
"Language-Team: Spanish <es@li.org>\n"
@@ -422,17 +422,17 @@ msgstr ""
"No hay configurada una cuota de salida para la red «%s», asignando el ancho "
"de banda predeterminado %llu\n"
-#: src/ats/gnunet-service-ats_addresses.c:2180
+#: src/ats/gnunet-service-ats_addresses.c:2184
#, c-format
msgid "Initializing solver `%s '`%s'\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2183
+#: src/ats/gnunet-service-ats_addresses.c:2187
#, fuzzy, c-format
msgid "Failed to initialize solver `%s'!\n"
msgstr "¡No se puede inicializar el resolvedor!\n"
-#: src/ats/gnunet-service-ats_addresses.c:2206
+#: src/ats/gnunet-service-ats_addresses.c:2210
#, fuzzy
msgid "Failed to initialize solver!\n"
msgstr "¡No se puede inicializar el resolvedor!\n"
@@ -4818,46 +4818,50 @@ msgstr "Se produjo un fallo al borrar el fichero de configuración %s\n"
msgid "Failed to create directory `%s' for storing egos\n"
msgstr "Se produjo un fallo al leer el directorio «%s»\n"
-#: src/mesh/gnunet-mesh.c:300
+#: src/mesh/gnunet-mesh.c:342
#, fuzzy, c-format
msgid "Invalid target `%s'\n"
msgstr "Parámetro no válido «%s»\n"
-#: src/mesh/gnunet-mesh.c:434
+#: src/mesh/gnunet-mesh.c:503
#, fuzzy, c-format
msgid "Invalid tunnel owner `%s'\n"
msgstr "Formato de tiempo no válido «%s»\n"
-#: src/mesh/gnunet-mesh.c:499
+#: src/mesh/gnunet-mesh.c:568
msgid "You must NOT give a TARGET when using options\n"
msgstr ""
-#: src/mesh/gnunet-mesh.c:576
+#: src/mesh/gnunet-mesh.c:645
#, fuzzy
msgid "provide information about a particular channel"
msgstr "proveer información acerca de un túnel en particular"
-#: src/mesh/gnunet-mesh.c:579
+#: src/mesh/gnunet-mesh.c:648
#, fuzzy
msgid "provide information about a particular connection"
msgstr "proveer información acerca de un túnel en particular"
-#: src/mesh/gnunet-mesh.c:582
+#: src/mesh/gnunet-mesh.c:651
+msgid "activate echo mode"
+msgstr ""
+
+#: src/mesh/gnunet-mesh.c:654
#, fuzzy
msgid "provide information about all tunnels"
msgstr "proveer información acerca de un túnel en particular"
-#: src/mesh/gnunet-mesh.c:585
+#: src/mesh/gnunet-mesh.c:657
msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED"
msgstr ""
"proveer información acerca de todos los túneles (de forma continua) SIN "
"IMPLEMENTAR"
-#: src/mesh/gnunet-mesh.c:588
+#: src/mesh/gnunet-mesh.c:660
msgid "port to listen to (default; 0)"
msgstr ""
-#: src/mesh/gnunet-mesh.c:591
+#: src/mesh/gnunet-mesh.c:663
msgid "provide information about a particular tunnel"
msgstr "proveer información acerca de un túnel en particular"
@@ -6121,7 +6125,7 @@ msgstr "¡Se produjo un fallo al conectar al servicio de estadísticas!\n"
msgid "Failed to send a message to the scalarproduct service\n"
msgstr "Se produjo un fallo al enviar una petición al servicio de transporte\n"
-#: src/set/gnunet-service-set.c:1403
+#: src/set/gnunet-service-set.c:1416
#, fuzzy
msgid "Could not connect to mesh service\n"
msgstr "¡No se pudo conectar al servicio %s!\n"
@@ -6263,6 +6267,16 @@ msgid ""
"deployments"
msgstr ""
+#: src/testbed/gnunet-daemon-testbed-underlay.c:300 src/testing/testing.c:293
+#: src/util/gnunet-ecc.c:217
+#, c-format
+msgid "Incorrect hostkey file format: %s\n"
+msgstr "El fichero de máquinas no tiene el formato correcto: %s\n"
+
+#: src/testbed/gnunet-daemon-testbed-underlay.c:553
+msgid "Daemon to restrict underlay network in testbed deployments"
+msgstr ""
+
#: src/testbed/gnunet-service-testbed_cpustatus.c:727
#, c-format
msgid ""
@@ -6490,11 +6504,6 @@ msgstr ""
msgid "Hostkeys file not found: %s\n"
msgstr "El fichero de máquinas no fue encontrado: %s\n"
-#: src/testing/testing.c:293 src/util/gnunet-ecc.c:217
-#, c-format
-msgid "Incorrect hostkey file format: %s\n"
-msgstr "El fichero de máquinas no tiene el formato correcto: %s\n"
-
#: src/testing/testing.c:716
#, c-format
msgid "Key number %u does not exist\n"
@@ -7393,39 +7402,39 @@ msgid "Unexpected address length: %u bytes\n"
msgstr "Longitud de dirección inesperada: %u bytes\n"
#: src/transport/plugin_transport_tcp.c:799
-#: src/transport/plugin_transport_tcp.c:979
+#: src/transport/plugin_transport_tcp.c:980
#: src/transport/plugin_transport_tcp.c:2120
#: src/transport/plugin_transport_tcp.c:2723
msgid "# TCP sessions active"
msgstr "# Sesiones TCP activas"
-#: src/transport/plugin_transport_tcp.c:835
-#: src/transport/plugin_transport_tcp.c:972
-#: src/transport/plugin_transport_tcp.c:1061
-#: src/transport/plugin_transport_tcp.c:1111
-#: src/transport/plugin_transport_tcp.c:1290
-#: src/transport/plugin_transport_tcp.c:1309
+#: src/transport/plugin_transport_tcp.c:836
+#: src/transport/plugin_transport_tcp.c:973
+#: src/transport/plugin_transport_tcp.c:1062
+#: src/transport/plugin_transport_tcp.c:1112
+#: src/transport/plugin_transport_tcp.c:1291
+#: src/transport/plugin_transport_tcp.c:1310
msgid "# bytes currently in TCP buffers"
msgstr "# bytes actualmente en los buffer TCP"
-#: src/transport/plugin_transport_tcp.c:839
+#: src/transport/plugin_transport_tcp.c:840
msgid "# bytes discarded by TCP (disconnect)"
msgstr "# bytes descartados por TCP (desconectado)"
-#: src/transport/plugin_transport_tcp.c:1065
+#: src/transport/plugin_transport_tcp.c:1066
msgid "# bytes discarded by TCP (timeout)"
msgstr "# bytes omitidos por TCP (expirados)"
-#: src/transport/plugin_transport_tcp.c:1114
+#: src/transport/plugin_transport_tcp.c:1115
msgid "# bytes transmitted via TCP"
msgstr "# bytes recibidos vía TCP"
-#: src/transport/plugin_transport_tcp.c:1263
+#: src/transport/plugin_transport_tcp.c:1264
#, c-format
msgid "Trying to send with invalid session %p\n"
msgstr "Intentando enviar con una sesión no válida %p\n"
-#: src/transport/plugin_transport_tcp.c:1520
+#: src/transport/plugin_transport_tcp.c:1521
#: src/transport/plugin_transport_udp.c:1488
msgid "# requests to create session with invalid address"
msgstr ""
@@ -8377,118 +8386,118 @@ msgstr "señal (%d, %p) devolvió %d.\n"
msgid "b"
msgstr "b"
-#: src/util/strings.c:452
+#: src/util/strings.c:444
#, c-format
msgid "Character sets requested were `%s'->`%s'\n"
msgstr "Los conjuntos de caracteres pedidos fueron «%s»->«%s»\n"
-#: src/util/strings.c:580
+#: src/util/strings.c:572
msgid "Failed to expand `$HOME': environment variable `HOME' not set"
msgstr ""
"Se produjo un fallo al expandir «$HOME»: variable de entorno «HOME» no "
"establecida"
-#: src/util/strings.c:677
+#: src/util/strings.c:669
msgid "µs"
msgstr ""
-#: src/util/strings.c:681
+#: src/util/strings.c:673
msgid "forever"
msgstr "para siempre"
-#: src/util/strings.c:683
+#: src/util/strings.c:675
msgid "0 ms"
msgstr "0 ms"
-#: src/util/strings.c:689
+#: src/util/strings.c:681
msgid "ms"
msgstr "ms"
-#: src/util/strings.c:695
+#: src/util/strings.c:687
msgid "s"
msgstr "s"
-#: src/util/strings.c:701
+#: src/util/strings.c:693
msgid "m"
msgstr "m"
-#: src/util/strings.c:707
+#: src/util/strings.c:699
msgid "h"
msgstr "h"
-#: src/util/strings.c:714
+#: src/util/strings.c:706
msgid "day"
msgstr "día"
-#: src/util/strings.c:716
+#: src/util/strings.c:708
msgid "days"
msgstr "días"
-#: src/util/strings.c:745
+#: src/util/strings.c:737
msgid "end of time"
msgstr "fin del plazo"
-#: src/util/strings.c:1178
+#: src/util/strings.c:1170
msgid "IPv6 address did not start with `['\n"
msgstr "La dirección IPv6 no empezaba con «[»\n"
-#: src/util/strings.c:1186
+#: src/util/strings.c:1178
msgid "IPv6 address did contain ':' to separate port number\n"
msgstr "La dirección IPv6 contenía «:» para separar el número de puerto\n"
-#: src/util/strings.c:1192
+#: src/util/strings.c:1184
msgid "IPv6 address did contain ']' before ':' to separate port number\n"
msgstr ""
"La dirección IPv6 contenía «]» antes de «:» para separar el número de "
"puerto\n"
-#: src/util/strings.c:1199
+#: src/util/strings.c:1191
msgid "IPv6 address did contain a valid port number after the last ':'\n"
msgstr ""
"La dirección IPv6 contenía un número de puerto válido después del último "
"«:»\n"
-#: src/util/strings.c:1208
+#: src/util/strings.c:1200
#, c-format
msgid "Invalid IPv6 address `%s': %s\n"
msgstr "Dirección IPv6 «%s» no válida: %s\n"
-#: src/util/strings.c:1414 src/util/strings.c:1430
+#: src/util/strings.c:1406 src/util/strings.c:1422
msgid "Port not in range\n"
msgstr ""
-#: src/util/strings.c:1439
+#: src/util/strings.c:1431
#, fuzzy, c-format
msgid "Malformed port policy `%s'\n"
msgstr "Se produjo un fallo al iniciar el servicio «%s»\n"
-#: src/util/strings.c:1522 src/util/strings.c:1553 src/util/strings.c:1601
-#: src/util/strings.c:1622
+#: src/util/strings.c:1514 src/util/strings.c:1545 src/util/strings.c:1593
+#: src/util/strings.c:1614
#, c-format
msgid "Invalid format for IP: `%s'\n"
msgstr "Formato no válido para la IP: «%s»\n"
-#: src/util/strings.c:1579
+#: src/util/strings.c:1571
#, c-format
msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
msgstr "Notación de red no válida («/%d» no es válido en IPv4 CIDR)."
-#: src/util/strings.c:1631
+#: src/util/strings.c:1623
#, fuzzy, c-format
msgid "Invalid format: `%s'\n"
msgstr "Formato de tiempo no válido «%s»\n"
-#: src/util/strings.c:1683
+#: src/util/strings.c:1675
#, c-format
msgid "Invalid network notation (does not end with ';': `%s')\n"
msgstr "Notación de red no válida (no termina con «;»: «%s»)\n"
-#: src/util/strings.c:1733
+#: src/util/strings.c:1725
#, c-format
msgid "Wrong format `%s' for netmask\n"
msgstr "Formato «%s» erroneo para máscara de red\n"
-#: src/util/strings.c:1764
+#: src/util/strings.c:1756
#, c-format
msgid "Wrong format `%s' for network\n"
msgstr "Formato «%s» erroneo para red\n"
diff --git a/po/sv.po b/po/sv.po
index a5806b593..286a17b9b 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: GNUnet 0.7.0b\n"
"Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2013-12-24 21:07+0100\n"
+"POT-Creation-Date: 2014-01-05 13:20+0100\n"
"PO-Revision-Date: 2006-01-21 17:16+0100\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -388,17 +388,17 @@ msgid ""
"%llu\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2180
+#: src/ats/gnunet-service-ats_addresses.c:2184
#, c-format
msgid "Initializing solver `%s '`%s'\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2183
+#: src/ats/gnunet-service-ats_addresses.c:2187
#, fuzzy, c-format
msgid "Failed to initialize solver `%s'!\n"
msgstr "Kunde inte initiera SQLite.\n"
-#: src/ats/gnunet-service-ats_addresses.c:2206
+#: src/ats/gnunet-service-ats_addresses.c:2210
#, fuzzy
msgid "Failed to initialize solver!\n"
msgstr "Kunde inte initiera SQLite.\n"
@@ -4722,45 +4722,49 @@ msgstr "Kunde inte spara konfigurationsfil \"%s\":"
msgid "Failed to create directory `%s' for storing egos\n"
msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
-#: src/mesh/gnunet-mesh.c:300
+#: src/mesh/gnunet-mesh.c:342
#, fuzzy, c-format
msgid "Invalid target `%s'\n"
msgstr "Ogiltigt argument: \"%s\"\n"
-#: src/mesh/gnunet-mesh.c:434
+#: src/mesh/gnunet-mesh.c:503
#, fuzzy, c-format
msgid "Invalid tunnel owner `%s'\n"
msgstr "Ogiltigt format för IP: \"%s\"\n"
-#: src/mesh/gnunet-mesh.c:499
+#: src/mesh/gnunet-mesh.c:568
msgid "You must NOT give a TARGET when using options\n"
msgstr ""
-#: src/mesh/gnunet-mesh.c:576
+#: src/mesh/gnunet-mesh.c:645
#, fuzzy
msgid "provide information about a particular channel"
msgstr "Skriv ut information om GNUnets motparter."
-#: src/mesh/gnunet-mesh.c:579
+#: src/mesh/gnunet-mesh.c:648
#, fuzzy
msgid "provide information about a particular connection"
msgstr "Skriv ut information om GNUnets motparter."
-#: src/mesh/gnunet-mesh.c:582
+#: src/mesh/gnunet-mesh.c:651
+msgid "activate echo mode"
+msgstr ""
+
+#: src/mesh/gnunet-mesh.c:654
#, fuzzy
msgid "provide information about all tunnels"
msgstr "Skriv ut information om GNUnets motparter."
-#: src/mesh/gnunet-mesh.c:585
+#: src/mesh/gnunet-mesh.c:657
#, fuzzy
msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED"
msgstr "Skriv ut information om GNUnets motparter."
-#: src/mesh/gnunet-mesh.c:588
+#: src/mesh/gnunet-mesh.c:660
msgid "port to listen to (default; 0)"
msgstr ""
-#: src/mesh/gnunet-mesh.c:591
+#: src/mesh/gnunet-mesh.c:663
#, fuzzy
msgid "provide information about a particular tunnel"
msgstr "Skriv ut information om GNUnets motparter."
@@ -6008,7 +6012,7 @@ msgstr "Misslyckades att ansluta till gnunetd.\n"
msgid "Failed to send a message to the scalarproduct service\n"
msgstr "Misslyckades att ansluta till gnunetd.\n"
-#: src/set/gnunet-service-set.c:1403
+#: src/set/gnunet-service-set.c:1416
#, fuzzy
msgid "Could not connect to mesh service\n"
msgstr "Kunde inte ansluta till gnunetd.\n"
@@ -6146,6 +6150,16 @@ msgid ""
"deployments"
msgstr ""
+#: src/testbed/gnunet-daemon-testbed-underlay.c:300 src/testing/testing.c:293
+#: src/util/gnunet-ecc.c:217
+#, c-format
+msgid "Incorrect hostkey file format: %s\n"
+msgstr ""
+
+#: src/testbed/gnunet-daemon-testbed-underlay.c:553
+msgid "Daemon to restrict underlay network in testbed deployments"
+msgstr ""
+
#: src/testbed/gnunet-service-testbed_cpustatus.c:727
#, c-format
msgid ""
@@ -6363,11 +6377,6 @@ msgstr ""
msgid "Hostkeys file not found: %s\n"
msgstr ""
-#: src/testing/testing.c:293 src/util/gnunet-ecc.c:217
-#, c-format
-msgid "Incorrect hostkey file format: %s\n"
-msgstr ""
-
#: src/testing/testing.c:716
#, fuzzy, c-format
msgid "Key number %u does not exist\n"
@@ -7245,44 +7254,44 @@ msgid "Unexpected address length: %u bytes\n"
msgstr ""
#: src/transport/plugin_transport_tcp.c:799
-#: src/transport/plugin_transport_tcp.c:979
+#: src/transport/plugin_transport_tcp.c:980
#: src/transport/plugin_transport_tcp.c:2120
#: src/transport/plugin_transport_tcp.c:2723
#, fuzzy
msgid "# TCP sessions active"
msgstr "# sessionsnycklar accepterade"
-#: src/transport/plugin_transport_tcp.c:835
-#: src/transport/plugin_transport_tcp.c:972
-#: src/transport/plugin_transport_tcp.c:1061
-#: src/transport/plugin_transport_tcp.c:1111
-#: src/transport/plugin_transport_tcp.c:1290
-#: src/transport/plugin_transport_tcp.c:1309
+#: src/transport/plugin_transport_tcp.c:836
+#: src/transport/plugin_transport_tcp.c:973
+#: src/transport/plugin_transport_tcp.c:1062
+#: src/transport/plugin_transport_tcp.c:1112
+#: src/transport/plugin_transport_tcp.c:1291
+#: src/transport/plugin_transport_tcp.c:1310
#, fuzzy
msgid "# bytes currently in TCP buffers"
msgstr "# byte skickades via TCP"
-#: src/transport/plugin_transport_tcp.c:839
+#: src/transport/plugin_transport_tcp.c:840
#, fuzzy
msgid "# bytes discarded by TCP (disconnect)"
msgstr "# byte kastade via TCP (utgående)"
-#: src/transport/plugin_transport_tcp.c:1065
+#: src/transport/plugin_transport_tcp.c:1066
#, fuzzy
msgid "# bytes discarded by TCP (timeout)"
msgstr "# byte kastade via TCP (utgående)"
-#: src/transport/plugin_transport_tcp.c:1114
+#: src/transport/plugin_transport_tcp.c:1115
#, fuzzy
msgid "# bytes transmitted via TCP"
msgstr "# byte skickade av typen %d"
-#: src/transport/plugin_transport_tcp.c:1263
+#: src/transport/plugin_transport_tcp.c:1264
#, c-format
msgid "Trying to send with invalid session %p\n"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:1520
+#: src/transport/plugin_transport_tcp.c:1521
#: src/transport/plugin_transport_udp.c:1488
msgid "# requests to create session with invalid address"
msgstr ""
@@ -8203,114 +8212,114 @@ msgstr "Anrop till \"%s\" returnerade %d.\n"
msgid "b"
msgstr "b"
-#: src/util/strings.c:452
+#: src/util/strings.c:444
#, c-format
msgid "Character sets requested were `%s'->`%s'\n"
msgstr ""
-#: src/util/strings.c:580
+#: src/util/strings.c:572
msgid "Failed to expand `$HOME': environment variable `HOME' not set"
msgstr ""
-#: src/util/strings.c:677
+#: src/util/strings.c:669
msgid "µs"
msgstr ""
-#: src/util/strings.c:681
+#: src/util/strings.c:673
msgid "forever"
msgstr ""
-#: src/util/strings.c:683
+#: src/util/strings.c:675
msgid "0 ms"
msgstr ""
-#: src/util/strings.c:689
+#: src/util/strings.c:681
msgid "ms"
msgstr "ms"
-#: src/util/strings.c:695
+#: src/util/strings.c:687
msgid "s"
msgstr "s"
-#: src/util/strings.c:701
+#: src/util/strings.c:693
msgid "m"
msgstr "m"
-#: src/util/strings.c:707
+#: src/util/strings.c:699
msgid "h"
msgstr "h"
-#: src/util/strings.c:714
+#: src/util/strings.c:706
#, fuzzy
msgid "day"
msgstr " dagar"
-#: src/util/strings.c:716
+#: src/util/strings.c:708
#, fuzzy
msgid "days"
msgstr " dagar"
-#: src/util/strings.c:745
+#: src/util/strings.c:737
msgid "end of time"
msgstr ""
-#: src/util/strings.c:1178
+#: src/util/strings.c:1170
msgid "IPv6 address did not start with `['\n"
msgstr ""
-#: src/util/strings.c:1186
+#: src/util/strings.c:1178
msgid "IPv6 address did contain ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1192
+#: src/util/strings.c:1184
msgid "IPv6 address did contain ']' before ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1199
+#: src/util/strings.c:1191
msgid "IPv6 address did contain a valid port number after the last ':'\n"
msgstr ""
-#: src/util/strings.c:1208
+#: src/util/strings.c:1200
#, fuzzy, c-format
msgid "Invalid IPv6 address `%s': %s\n"
msgstr "Ogiltigt svar på \"%s\".\n"
-#: src/util/strings.c:1414 src/util/strings.c:1430
+#: src/util/strings.c:1406 src/util/strings.c:1422
msgid "Port not in range\n"
msgstr ""
-#: src/util/strings.c:1439
+#: src/util/strings.c:1431
#, fuzzy, c-format
msgid "Malformed port policy `%s'\n"
msgstr "Misslyckades att starta samling.\n"
-#: src/util/strings.c:1522 src/util/strings.c:1553 src/util/strings.c:1601
-#: src/util/strings.c:1622
+#: src/util/strings.c:1514 src/util/strings.c:1545 src/util/strings.c:1593
+#: src/util/strings.c:1614
#, c-format
msgid "Invalid format for IP: `%s'\n"
msgstr "Ogiltigt format för IP: \"%s\"\n"
-#: src/util/strings.c:1579
+#: src/util/strings.c:1571
#, c-format
msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
msgstr "Ogiltig nätverksnotation (\"/%d\" är inte giltig i IPv4 CIDR)."
-#: src/util/strings.c:1631
+#: src/util/strings.c:1623
#, fuzzy, c-format
msgid "Invalid format: `%s'\n"
msgstr "Ogiltigt format för IP: \"%s\"\n"
-#: src/util/strings.c:1683
+#: src/util/strings.c:1675
#, c-format
msgid "Invalid network notation (does not end with ';': `%s')\n"
msgstr "Ogiltig nätverksnotation (slutar inte med \";\": \"%s\")\n"
-#: src/util/strings.c:1733
+#: src/util/strings.c:1725
#, fuzzy, c-format
msgid "Wrong format `%s' for netmask\n"
msgstr "Fel format \"%s\" för nätmask: %s\n"
-#: src/util/strings.c:1764
+#: src/util/strings.c:1756
#, fuzzy, c-format
msgid "Wrong format `%s' for network\n"
msgstr "Fel format \"%s\" för nätverk: %s\n"
diff --git a/po/vi.po b/po/vi.po
index d9958a433..5176d83aa 100644
--- a/po/vi.po
+++ b/po/vi.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gnunet 0.8.0a\n"
"Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2013-12-24 21:07+0100\n"
+"POT-Creation-Date: 2014-01-05 13:20+0100\n"
"PO-Revision-Date: 2008-09-10 22:05+0930\n"
"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
"Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
@@ -394,17 +394,17 @@ msgid ""
"%llu\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2180
+#: src/ats/gnunet-service-ats_addresses.c:2184
#, c-format
msgid "Initializing solver `%s '`%s'\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2183
+#: src/ats/gnunet-service-ats_addresses.c:2187
#, fuzzy, c-format
msgid "Failed to initialize solver `%s'!\n"
msgstr "Không thể sơ khởi SQLite: %s.\n"
-#: src/ats/gnunet-service-ats_addresses.c:2206
+#: src/ats/gnunet-service-ats_addresses.c:2210
#, fuzzy
msgid "Failed to initialize solver!\n"
msgstr "Không thể sơ khởi SQLite: %s.\n"
@@ -4786,45 +4786,49 @@ msgstr "Không thể lưu tập tin cấu hình « %s »:"
msgid "Failed to create directory `%s' for storing egos\n"
msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
-#: src/mesh/gnunet-mesh.c:300
+#: src/mesh/gnunet-mesh.c:342
#, fuzzy, c-format
msgid "Invalid target `%s'\n"
msgstr "Đối số không hợp lệ cho « %s ».\n"
-#: src/mesh/gnunet-mesh.c:434
+#: src/mesh/gnunet-mesh.c:503
#, fuzzy, c-format
msgid "Invalid tunnel owner `%s'\n"
msgstr "Địa chỉ IP định dạng sai: %s\n"
-#: src/mesh/gnunet-mesh.c:499
+#: src/mesh/gnunet-mesh.c:568
msgid "You must NOT give a TARGET when using options\n"
msgstr ""
-#: src/mesh/gnunet-mesh.c:576
+#: src/mesh/gnunet-mesh.c:645
#, fuzzy
msgid "provide information about a particular channel"
msgstr "In ra thông tin về các đồng đẳng GNUnet."
-#: src/mesh/gnunet-mesh.c:579
+#: src/mesh/gnunet-mesh.c:648
#, fuzzy
msgid "provide information about a particular connection"
msgstr "In ra thông tin về các đồng đẳng GNUnet."
-#: src/mesh/gnunet-mesh.c:582
+#: src/mesh/gnunet-mesh.c:651
+msgid "activate echo mode"
+msgstr ""
+
+#: src/mesh/gnunet-mesh.c:654
#, fuzzy
msgid "provide information about all tunnels"
msgstr "In ra thông tin về các đồng đẳng GNUnet."
-#: src/mesh/gnunet-mesh.c:585
+#: src/mesh/gnunet-mesh.c:657
#, fuzzy
msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED"
msgstr "In ra thông tin về các đồng đẳng GNUnet."
-#: src/mesh/gnunet-mesh.c:588
+#: src/mesh/gnunet-mesh.c:660
msgid "port to listen to (default; 0)"
msgstr ""
-#: src/mesh/gnunet-mesh.c:591
+#: src/mesh/gnunet-mesh.c:663
#, fuzzy
msgid "provide information about a particular tunnel"
msgstr "In ra thông tin về các đồng đẳng GNUnet."
@@ -6071,7 +6075,7 @@ msgstr "Lỗi kết nối đến gnunetd.\n"
msgid "Failed to send a message to the scalarproduct service\n"
msgstr "Lỗi kết nối đến gnunetd.\n"
-#: src/set/gnunet-service-set.c:1403
+#: src/set/gnunet-service-set.c:1416
#, fuzzy
msgid "Could not connect to mesh service\n"
msgstr "Không thể kết nối tới %s:%u: %s\n"
@@ -6209,6 +6213,16 @@ msgid ""
"deployments"
msgstr ""
+#: src/testbed/gnunet-daemon-testbed-underlay.c:300 src/testing/testing.c:293
+#: src/util/gnunet-ecc.c:217
+#, c-format
+msgid "Incorrect hostkey file format: %s\n"
+msgstr ""
+
+#: src/testbed/gnunet-daemon-testbed-underlay.c:553
+msgid "Daemon to restrict underlay network in testbed deployments"
+msgstr ""
+
#: src/testbed/gnunet-service-testbed_cpustatus.c:727
#, c-format
msgid ""
@@ -6426,11 +6440,6 @@ msgstr ""
msgid "Hostkeys file not found: %s\n"
msgstr ""
-#: src/testing/testing.c:293 src/util/gnunet-ecc.c:217
-#, c-format
-msgid "Incorrect hostkey file format: %s\n"
-msgstr ""
-
#: src/testing/testing.c:716
#, fuzzy, c-format
msgid "Key number %u does not exist\n"
@@ -7308,44 +7317,44 @@ msgid "Unexpected address length: %u bytes\n"
msgstr "Gặp sự kiện bất thường: %d\n"
#: src/transport/plugin_transport_tcp.c:799
-#: src/transport/plugin_transport_tcp.c:979
+#: src/transport/plugin_transport_tcp.c:980
#: src/transport/plugin_transport_tcp.c:2120
#: src/transport/plugin_transport_tcp.c:2723
#, fuzzy
msgid "# TCP sessions active"
msgstr "# các khoá phiên chạy được chấp nhận"
-#: src/transport/plugin_transport_tcp.c:835
-#: src/transport/plugin_transport_tcp.c:972
-#: src/transport/plugin_transport_tcp.c:1061
-#: src/transport/plugin_transport_tcp.c:1111
-#: src/transport/plugin_transport_tcp.c:1290
-#: src/transport/plugin_transport_tcp.c:1309
+#: src/transport/plugin_transport_tcp.c:836
+#: src/transport/plugin_transport_tcp.c:973
+#: src/transport/plugin_transport_tcp.c:1062
+#: src/transport/plugin_transport_tcp.c:1112
+#: src/transport/plugin_transport_tcp.c:1291
+#: src/transport/plugin_transport_tcp.c:1310
#, fuzzy
msgid "# bytes currently in TCP buffers"
msgstr "# các byte đã gừi qua TCP"
-#: src/transport/plugin_transport_tcp.c:839
+#: src/transport/plugin_transport_tcp.c:840
#, fuzzy
msgid "# bytes discarded by TCP (disconnect)"
msgstr "# các byte loại đi bởi TCP (đi ra)"
-#: src/transport/plugin_transport_tcp.c:1065
+#: src/transport/plugin_transport_tcp.c:1066
#, fuzzy
msgid "# bytes discarded by TCP (timeout)"
msgstr "# các byte loại đi bởi TCP (đi ra)"
-#: src/transport/plugin_transport_tcp.c:1114
+#: src/transport/plugin_transport_tcp.c:1115
#, fuzzy
msgid "# bytes transmitted via TCP"
msgstr "# các byte được gửi"
-#: src/transport/plugin_transport_tcp.c:1263
+#: src/transport/plugin_transport_tcp.c:1264
#, c-format
msgid "Trying to send with invalid session %p\n"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:1520
+#: src/transport/plugin_transport_tcp.c:1521
#: src/transport/plugin_transport_udp.c:1488
msgid "# requests to create session with invalid address"
msgstr ""
@@ -8265,115 +8274,115 @@ msgstr ""
msgid "b"
msgstr "b"
-#: src/util/strings.c:452
+#: src/util/strings.c:444
#, c-format
msgid "Character sets requested were `%s'->`%s'\n"
msgstr ""
-#: src/util/strings.c:580
+#: src/util/strings.c:572
msgid "Failed to expand `$HOME': environment variable `HOME' not set"
msgstr ""
"Lỗi mở rộng biến môi trường « $HOME »: chưa đặt biến môi trường « HOME »"
-#: src/util/strings.c:677
+#: src/util/strings.c:669
msgid "µs"
msgstr ""
-#: src/util/strings.c:681
+#: src/util/strings.c:673
msgid "forever"
msgstr ""
-#: src/util/strings.c:683
+#: src/util/strings.c:675
msgid "0 ms"
msgstr ""
-#: src/util/strings.c:689
+#: src/util/strings.c:681
msgid "ms"
msgstr "mg"
-#: src/util/strings.c:695
+#: src/util/strings.c:687
msgid "s"
msgstr "g"
-#: src/util/strings.c:701
+#: src/util/strings.c:693
msgid "m"
msgstr "p"
-#: src/util/strings.c:707
+#: src/util/strings.c:699
msgid "h"
msgstr "g"
-#: src/util/strings.c:714
+#: src/util/strings.c:706
#, fuzzy
msgid "day"
msgstr " ngày"
-#: src/util/strings.c:716
+#: src/util/strings.c:708
#, fuzzy
msgid "days"
msgstr " ngày"
-#: src/util/strings.c:745
+#: src/util/strings.c:737
msgid "end of time"
msgstr ""
-#: src/util/strings.c:1178
+#: src/util/strings.c:1170
msgid "IPv6 address did not start with `['\n"
msgstr ""
-#: src/util/strings.c:1186
+#: src/util/strings.c:1178
msgid "IPv6 address did contain ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1192
+#: src/util/strings.c:1184
msgid "IPv6 address did contain ']' before ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1199
+#: src/util/strings.c:1191
msgid "IPv6 address did contain a valid port number after the last ':'\n"
msgstr ""
-#: src/util/strings.c:1208
+#: src/util/strings.c:1200
#, fuzzy, c-format
msgid "Invalid IPv6 address `%s': %s\n"
msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n"
-#: src/util/strings.c:1414 src/util/strings.c:1430
+#: src/util/strings.c:1406 src/util/strings.c:1422
msgid "Port not in range\n"
msgstr ""
-#: src/util/strings.c:1439
+#: src/util/strings.c:1431
#, fuzzy, c-format
msgid "Malformed port policy `%s'\n"
msgstr "Lỗi bắt đầu thu thập.\n"
-#: src/util/strings.c:1522 src/util/strings.c:1553 src/util/strings.c:1601
-#: src/util/strings.c:1622
+#: src/util/strings.c:1514 src/util/strings.c:1545 src/util/strings.c:1593
+#: src/util/strings.c:1614
#, c-format
msgid "Invalid format for IP: `%s'\n"
msgstr "Địa chỉ IP định dạng sai: %s\n"
-#: src/util/strings.c:1579
+#: src/util/strings.c:1571
#, c-format
msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
msgstr "Ký hiệu mạng sai (« /%d » không hợp lệ trong CIDR IPv4)."
-#: src/util/strings.c:1631
+#: src/util/strings.c:1623
#, fuzzy, c-format
msgid "Invalid format: `%s'\n"
msgstr "Địa chỉ IP định dạng sai: %s\n"
-#: src/util/strings.c:1683
+#: src/util/strings.c:1675
#, c-format
msgid "Invalid network notation (does not end with ';': `%s')\n"
msgstr "Ký hiệu mạng sai (không kết thúc với « ; »: « %s »)\n"
-#: src/util/strings.c:1733
+#: src/util/strings.c:1725
#, fuzzy, c-format
msgid "Wrong format `%s' for netmask\n"
msgstr "Mặt nạ mạng có định dạng sai « %s »: %s\n"
-#: src/util/strings.c:1764
+#: src/util/strings.c:1756
#, fuzzy, c-format
msgid "Wrong format `%s' for network\n"
msgstr "Mạng có định dạng sai « %s »: %s\n"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 0ba9bfdf8..966abf80b 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gnunet-0.8.1\n"
"Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2013-12-24 21:07+0100\n"
+"POT-Creation-Date: 2014-01-05 13:20+0100\n"
"PO-Revision-Date: 2011-07-09 12:12+0800\n"
"Last-Translator: Wylmer Wang <wantinghard@gmail.com>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@@ -387,17 +387,17 @@ msgid ""
"%llu\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2180
+#: src/ats/gnunet-service-ats_addresses.c:2184
#, c-format
msgid "Initializing solver `%s '`%s'\n"
msgstr ""
-#: src/ats/gnunet-service-ats_addresses.c:2183
+#: src/ats/gnunet-service-ats_addresses.c:2187
#, fuzzy, c-format
msgid "Failed to initialize solver `%s'!\n"
msgstr "无法初始化 SQLite:%s。\n"
-#: src/ats/gnunet-service-ats_addresses.c:2206
+#: src/ats/gnunet-service-ats_addresses.c:2210
#, fuzzy
msgid "Failed to initialize solver!\n"
msgstr "无法初始化 SQLite:%s。\n"
@@ -4564,44 +4564,48 @@ msgstr "解析配置文件“%s”失败\n"
msgid "Failed to create directory `%s' for storing egos\n"
msgstr "解析配置文件“%s”失败\n"
-#: src/mesh/gnunet-mesh.c:300
+#: src/mesh/gnunet-mesh.c:342
#, fuzzy, c-format
msgid "Invalid target `%s'\n"
msgstr "“%s”的参数无效。\n"
-#: src/mesh/gnunet-mesh.c:434
+#: src/mesh/gnunet-mesh.c:503
#, fuzzy, c-format
msgid "Invalid tunnel owner `%s'\n"
msgstr "IP 格式无效:“%s”\n"
-#: src/mesh/gnunet-mesh.c:499
+#: src/mesh/gnunet-mesh.c:568
msgid "You must NOT give a TARGET when using options\n"
msgstr ""
-#: src/mesh/gnunet-mesh.c:576
+#: src/mesh/gnunet-mesh.c:645
#, fuzzy
msgid "provide information about a particular channel"
msgstr "无法获取有关用户“%s”的信息:%s\n"
-#: src/mesh/gnunet-mesh.c:579
+#: src/mesh/gnunet-mesh.c:648
#, fuzzy
msgid "provide information about a particular connection"
msgstr "无法获取有关用户“%s”的信息:%s\n"
-#: src/mesh/gnunet-mesh.c:582
+#: src/mesh/gnunet-mesh.c:651
+msgid "activate echo mode"
+msgstr ""
+
+#: src/mesh/gnunet-mesh.c:654
#, fuzzy
msgid "provide information about all tunnels"
msgstr "无法获取有关用户“%s”的信息:%s\n"
-#: src/mesh/gnunet-mesh.c:585
+#: src/mesh/gnunet-mesh.c:657
msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED"
msgstr ""
-#: src/mesh/gnunet-mesh.c:588
+#: src/mesh/gnunet-mesh.c:660
msgid "port to listen to (default; 0)"
msgstr ""
-#: src/mesh/gnunet-mesh.c:591
+#: src/mesh/gnunet-mesh.c:663
#, fuzzy
msgid "provide information about a particular tunnel"
msgstr "无法获取有关用户“%s”的信息:%s\n"
@@ -5821,7 +5825,7 @@ msgstr "初始化“%s”服务失败。\n"
msgid "Failed to send a message to the scalarproduct service\n"
msgstr "初始化“%s”服务失败。\n"
-#: src/set/gnunet-service-set.c:1403
+#: src/set/gnunet-service-set.c:1416
#, fuzzy
msgid "Could not connect to mesh service\n"
msgstr "无法连接到 %s:%u:%s\n"
@@ -5959,6 +5963,16 @@ msgid ""
"deployments"
msgstr ""
+#: src/testbed/gnunet-daemon-testbed-underlay.c:300 src/testing/testing.c:293
+#: src/util/gnunet-ecc.c:217
+#, c-format
+msgid "Incorrect hostkey file format: %s\n"
+msgstr ""
+
+#: src/testbed/gnunet-daemon-testbed-underlay.c:553
+msgid "Daemon to restrict underlay network in testbed deployments"
+msgstr ""
+
#: src/testbed/gnunet-service-testbed_cpustatus.c:727
#, c-format
msgid ""
@@ -6175,11 +6189,6 @@ msgstr ""
msgid "Hostkeys file not found: %s\n"
msgstr ""
-#: src/testing/testing.c:293 src/util/gnunet-ecc.c:217
-#, c-format
-msgid "Incorrect hostkey file format: %s\n"
-msgstr ""
-
#: src/testing/testing.c:716
#, c-format
msgid "Key number %u does not exist\n"
@@ -7007,39 +7016,39 @@ msgid "Unexpected address length: %u bytes\n"
msgstr ""
#: src/transport/plugin_transport_tcp.c:799
-#: src/transport/plugin_transport_tcp.c:979
+#: src/transport/plugin_transport_tcp.c:980
#: src/transport/plugin_transport_tcp.c:2120
#: src/transport/plugin_transport_tcp.c:2723
msgid "# TCP sessions active"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:835
-#: src/transport/plugin_transport_tcp.c:972
-#: src/transport/plugin_transport_tcp.c:1061
-#: src/transport/plugin_transport_tcp.c:1111
-#: src/transport/plugin_transport_tcp.c:1290
-#: src/transport/plugin_transport_tcp.c:1309
+#: src/transport/plugin_transport_tcp.c:836
+#: src/transport/plugin_transport_tcp.c:973
+#: src/transport/plugin_transport_tcp.c:1062
+#: src/transport/plugin_transport_tcp.c:1112
+#: src/transport/plugin_transport_tcp.c:1291
+#: src/transport/plugin_transport_tcp.c:1310
msgid "# bytes currently in TCP buffers"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:839
+#: src/transport/plugin_transport_tcp.c:840
msgid "# bytes discarded by TCP (disconnect)"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:1065
+#: src/transport/plugin_transport_tcp.c:1066
msgid "# bytes discarded by TCP (timeout)"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:1114
+#: src/transport/plugin_transport_tcp.c:1115
msgid "# bytes transmitted via TCP"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:1263
+#: src/transport/plugin_transport_tcp.c:1264
#, c-format
msgid "Trying to send with invalid session %p\n"
msgstr ""
-#: src/transport/plugin_transport_tcp.c:1520
+#: src/transport/plugin_transport_tcp.c:1521
#: src/transport/plugin_transport_udp.c:1488
msgid "# requests to create session with invalid address"
msgstr ""
@@ -7938,114 +7947,114 @@ msgstr ""
msgid "b"
msgstr "b"
-#: src/util/strings.c:452
+#: src/util/strings.c:444
#, c-format
msgid "Character sets requested were `%s'->`%s'\n"
msgstr ""
-#: src/util/strings.c:580
+#: src/util/strings.c:572
msgid "Failed to expand `$HOME': environment variable `HOME' not set"
msgstr "扩展“$HOME”失败:没有设置环境变量“HOME”"
-#: src/util/strings.c:677
+#: src/util/strings.c:669
msgid "µs"
msgstr ""
-#: src/util/strings.c:681
+#: src/util/strings.c:673
msgid "forever"
msgstr ""
-#: src/util/strings.c:683
+#: src/util/strings.c:675
msgid "0 ms"
msgstr ""
-#: src/util/strings.c:689
+#: src/util/strings.c:681
msgid "ms"
msgstr "毫秒"
-#: src/util/strings.c:695
+#: src/util/strings.c:687
msgid "s"
msgstr "秒"
-#: src/util/strings.c:701
+#: src/util/strings.c:693
msgid "m"
msgstr "分"
-#: src/util/strings.c:707
+#: src/util/strings.c:699
msgid "h"
msgstr "时"
-#: src/util/strings.c:714
+#: src/util/strings.c:706
#, fuzzy
msgid "day"
msgstr " 天"
-#: src/util/strings.c:716
+#: src/util/strings.c:708
#, fuzzy
msgid "days"
msgstr " 天"
-#: src/util/strings.c:745
+#: src/util/strings.c:737
msgid "end of time"
msgstr ""
-#: src/util/strings.c:1178
+#: src/util/strings.c:1170
msgid "IPv6 address did not start with `['\n"
msgstr ""
-#: src/util/strings.c:1186
+#: src/util/strings.c:1178
msgid "IPv6 address did contain ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1192
+#: src/util/strings.c:1184
msgid "IPv6 address did contain ']' before ':' to separate port number\n"
msgstr ""
-#: src/util/strings.c:1199
+#: src/util/strings.c:1191
msgid "IPv6 address did contain a valid port number after the last ':'\n"
msgstr ""
-#: src/util/strings.c:1208
+#: src/util/strings.c:1200
#, fuzzy, c-format
msgid "Invalid IPv6 address `%s': %s\n"
msgstr "无效的进程优先级“%s”\n"
-#: src/util/strings.c:1414 src/util/strings.c:1430
+#: src/util/strings.c:1406 src/util/strings.c:1422
msgid "Port not in range\n"
msgstr ""
-#: src/util/strings.c:1439
+#: src/util/strings.c:1431
#, fuzzy, c-format
msgid "Malformed port policy `%s'\n"
msgstr "解析配置文件“%s”失败\n"
-#: src/util/strings.c:1522 src/util/strings.c:1553 src/util/strings.c:1601
-#: src/util/strings.c:1622
+#: src/util/strings.c:1514 src/util/strings.c:1545 src/util/strings.c:1593
+#: src/util/strings.c:1614
#, c-format
msgid "Invalid format for IP: `%s'\n"
msgstr "IP 格式无效:“%s”\n"
-#: src/util/strings.c:1579
+#: src/util/strings.c:1571
#, c-format
msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
msgstr "网络表示法无效(“/%d” 在 IPv4 CIDR 中是非法的)。"
-#: src/util/strings.c:1631
+#: src/util/strings.c:1623
#, fuzzy, c-format
msgid "Invalid format: `%s'\n"
msgstr "IP 格式无效:“%s”\n"
-#: src/util/strings.c:1683
+#: src/util/strings.c:1675
#, c-format
msgid "Invalid network notation (does not end with ';': `%s')\n"
msgstr "无效的网络表示法(没有以“;”结尾:“%s”)\n"
-#: src/util/strings.c:1733
+#: src/util/strings.c:1725
#, c-format
msgid "Wrong format `%s' for netmask\n"
msgstr "网络掩码的格式“%s”错误\n"
-#: src/util/strings.c:1764
+#: src/util/strings.c:1756
#, c-format
msgid "Wrong format `%s' for network\n"
msgstr "网络的格式“%s”错误\n"
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index f1049e1cd..a752988fd 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -56,12 +56,15 @@ struct GNUNET_CONSENSUS_ConcludeMessage
*/
struct GNUNET_MessageHeader header;
- // uint32_t reserved GNUNET_PACKED; // FIXME...
+ /**
+ * Padding, must be zero.
+ */
+ uint32_t reserved GNUNET_PACKED;
/**
- * Timeout for conclude
+ * Deadline for conclude
*/
- struct GNUNET_TIME_RelativeNBO timeout;
+ struct GNUNET_TIME_AbsoluteNBO deadline;
};
diff --git a/src/consensus/consensus_api.c b/src/consensus/consensus_api.c
index 0a2a7d7ac..14a1bf54e 100644
--- a/src/consensus/consensus_api.c
+++ b/src/consensus/consensus_api.c
@@ -259,14 +259,14 @@ GNUNET_CONSENSUS_insert (struct GNUNET_CONSENSUS_Handle *consensus,
* inserted by the client.
*
* @param consensus consensus session
- * @param timeout timeout after which the conculde callback
+ * @param deadline deadline after which the conculde callback
* must be called
* @param conclude called when the conclusion was successful
* @param conclude_cls closure for the conclude callback
*/
void
GNUNET_CONSENSUS_conclude (struct GNUNET_CONSENSUS_Handle *consensus,
- struct GNUNET_TIME_Relative timeout,
+ struct GNUNET_TIME_Absolute deadline,
GNUNET_CONSENSUS_ConcludeCallback conclude,
void *conclude_cls)
{
@@ -280,7 +280,7 @@ GNUNET_CONSENSUS_conclude (struct GNUNET_CONSENSUS_Handle *consensus,
consensus->conclude_cb = conclude;
ev = GNUNET_MQ_msg (conclude_msg, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE);
- conclude_msg->timeout = GNUNET_TIME_relative_hton (timeout);
+ conclude_msg->deadline = GNUNET_TIME_absolute_hton (deadline);
GNUNET_MQ_send (consensus->mq, ev);
}
diff --git a/src/consensus/gnunet-consensus-profiler.c b/src/consensus/gnunet-consensus-profiler.c
index 6b01f9d8e..272a675db 100644
--- a/src/consensus/gnunet-consensus-profiler.c
+++ b/src/consensus/gnunet-consensus-profiler.c
@@ -172,7 +172,7 @@ do_consensus ()
for (i = 0; i < num_peers; i++)
GNUNET_CONSENSUS_conclude (consensus_handles[i],
- conclude_timeout,
+ GNUNET_TIME_relative_to_absolute (conclude_timeout),
conclude_cb, &consensus_handles[i]);
}
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c
index 914943f11..688190c14 100644
--- a/src/consensus/gnunet-service-consensus.c
+++ b/src/consensus/gnunet-service-consensus.c
@@ -146,7 +146,7 @@ struct ConsensusSession
* with a fraction of the conclude timeout.
* Only valid once the current round is not CONSENSUS_ROUND_BEGIN.
*/
- struct GNUNET_TIME_Relative conclude_timeout;
+ struct GNUNET_TIME_Absolute conclude_deadline;
/**
* Timeout task identifier for the current round.
@@ -1194,7 +1194,7 @@ client_conclude (void *cls,
}
else
{
- session->conclude_timeout = GNUNET_TIME_relative_ntoh (cmsg->timeout);
+ session->conclude_deadline = GNUNET_TIME_absolute_ntoh (cmsg->deadline);
/* the 'begin' round is over, start with the next, actual round */
round_over (session, NULL);
}
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index e593826b7..e4423f145 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -682,6 +682,17 @@ GNUNET_ntoh_double (double d);
/**
* @ingroup memory
+ * Allocate a size @a n array with structs or unions of the given @a type.
+ * Wrapper around #GNUNET_malloc that returns a pointer
+ * to the newly created objects of the correct type.
+ *
+ * @param n number of elements in the array
+ * @param type name of the struct or union, i.e. pass 'struct Foo'.
+ */
+#define GNUNET_new_array(n, type) (type *) GNUNET_malloc ((n) * sizeof (type))
+
+/**
+ * @ingroup memory
* Wrapper around malloc. Allocates size bytes of memory.
* The memory will be zero'ed out.
*
diff --git a/src/include/gnunet_consensus_service.h b/src/include/gnunet_consensus_service.h
index 6d8d23a17..3b08b2dee 100644
--- a/src/include/gnunet_consensus_service.h
+++ b/src/include/gnunet_consensus_service.h
@@ -73,7 +73,7 @@ struct GNUNET_CONSENSUS_Handle;
* @param session_id session identifier
* Allows a group of peers to have more than consensus session.
* @param new_element_cb callback, called when a new element is added to the set by
- * another peer
+ * another peer. Also called when an error occurs.
* @param new_element_cls closure for new_element
* @return handle to use, NULL on error
*/
@@ -135,14 +135,14 @@ typedef void (*GNUNET_CONSENSUS_ConcludeCallback) (void *cls);
* try to conclude the consensus within a given time window.
*
* @param consensus consensus session
- * @param timeout timeout after which the conculde callback
- * must be called
+ * @param deadline deadline after which the conculde callback
+ * whill be called
* @param conclude called when the conclusion was successful
* @param conclude_cls closure for the conclude callback
*/
void
GNUNET_CONSENSUS_conclude (struct GNUNET_CONSENSUS_Handle *consensus,
- struct GNUNET_TIME_Relative timeout,
+ struct GNUNET_TIME_Absolute deadline,
GNUNET_CONSENSUS_ConcludeCallback conclude,
void *conclude_cls);
diff --git a/src/include/gnunet_secretsharing_service.h b/src/include/gnunet_secretsharing_service.h
index 7eb372ef5..8569e15ea 100644
--- a/src/include/gnunet_secretsharing_service.h
+++ b/src/include/gnunet_secretsharing_service.h
@@ -46,6 +46,8 @@ extern "C"
* Number of bits for secretsharing keys.
* Must be smaller than the Pallier key size used internally
* by the secretsharing service.
+ * When changing this value, other internal parameters must also
+ * be adjusted.
*/
#define GNUNET_SECRETSHARING_KEY_BITS 1024
@@ -58,8 +60,8 @@ struct GNUNET_SECRETSHARING_Session;
/**
* Share of a secret shared with a group of peers.
- * Contains both the share and information about the peers that have
- * the other parts of the share.
+ * Contains the secret share itself, the public key, the list of peers, and the
+ * exponential commitments to the secret shares of the other peers.
*/
struct GNUNET_SECRETSHARING_Share;
@@ -84,7 +86,8 @@ struct GNUNET_SECRETSHARING_PublicKey
*/
struct GNUNET_SECRETSHARING_Ciphertext
{
- uint32_t bits[2 * GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)];
+ uint32_t c1_bits[GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)];
+ uint32_t c2_bits[GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)];
};
@@ -97,7 +100,7 @@ struct GNUNET_SECRETSHARING_Message
/**
* Value of the message.
*/
- gcry_mpi_t value;
+ uint32_t bits[GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)];
};
@@ -206,15 +209,19 @@ GNUNET_SECRETSHARING_encrypt (struct GNUNET_SECRETSHARING_PublicKey *public_key,
* When the operation is canceled, the decrypt_cb is not called anymore, but the calling
* peer may already have irrevocably contributed his share for the decryption of the value.
*
+ * @param cfg configuration to use
* @param share our secret share to use for decryption
* @param ciphertext ciphertext to publish in order to decrypt it (if enough peers agree)
* @param decrypt_cb callback called once the decryption succeeded
+ * @param deadline By when should the decryption be finished?
* @param decrypt_cb_cls closure for @a decrypt_cb
* @return handle to cancel the operation
*/
struct GNUNET_SECRETSHARING_DecryptionHandle *
-GNUNET_SECRETSHARING_decrypt (struct GNUNET_SECRETSHARING_Share *share,
+GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_SECRETSHARING_Share *share,
struct GNUNET_SECRETSHARING_Ciphertext *ciphertext,
+ struct GNUNET_TIME_Absolute deadline,
GNUNET_SECRETSHARING_DecryptCallback decrypt_cb,
void *decrypt_cb_cls);
@@ -234,41 +241,32 @@ GNUNET_SECRETSHARING_decrypt_cancel (struct GNUNET_SECRETSHARING_DecryptionHandl
/**
* Read a share from its binary representation.
*
- * @param data binary representation of the share
- * @param len length of @a data
- * @return the share, or NULL on error
+ * @param data Binary representation of the share.
+ * @param len Length of @a data.
+ * @param[out] readlen Number of bytes read,
+ * ignored if NULL.
+ * @return The share, or NULL on error.
*/
struct GNUNET_SECRETSHARING_Share *
-GNUNET_SECRETSHARING_share_read (void *data, size_t len);
+GNUNET_SECRETSHARING_share_read (const void *data, size_t len, size_t *readlen);
/**
- * Convert a share to its binary representation. Use
- * #GNUNET_SECRETSHARING_share_size to get the necessary size for the binary
- * representation.
+ * Convert a share to its binary representation.
+ * Can be called with a NULL @a buf to get the size of the share.
*
- * @param share share to write
- * @param buf buffer to write to
- * @param buflen number of writable bytes in @a buffer
- * @param[out] writelen pointer to store number of bytes written,
- * ignored if NULL
- * @return GNUNET_YES on success, GNUNET_NO on failure
+ * @param share Share to write.
+ * @param buf Buffer to write to.
+ * @param buflen Number of writable bytes in @a buf.
+ * @param[out] writelen Pointer to store number of bytes written,
+ * ignored if NULL.
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure.
*/
int
-GNUNET_SECRETSHARING_share_write (struct GNUNET_SECRETSHARING_Share *share,
+GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share,
void *buf, size_t buflen, size_t *writelen);
-/**
- * Get the number of bytes necessary to represent the given share.
- *
- * @param share share
- * @return number of bytes necessary to represent @a share
- */
-size_t
-GNUNET_SECRETSHARING_share_size (struct GNUNET_SECRETSHARING_Share *share);
-
-
#if 0 /* keep Emacsens' auto-indent happy */
{
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index f8839c1aa..05d758cdb 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -151,6 +151,21 @@ extern "C"
*/
#define GNUNET_SIGNATURE_PURPOSE_MESH_KX 21
+/**
+ * Signature for the first round of distributed key generation.
+ */
+#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1 22
+
+/**
+ * Signature for the second round of distributed key generation.
+ */
+#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2 23
+
+/**
+ * Signature for cooperatice decryption.
+ */
+#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION 23
+
#if 0 /* keep Emacsens' auto-indent happy */
{
diff --git a/src/secretsharing/Makefile.am b/src/secretsharing/Makefile.am
index 0473820b2..f2e14a60c 100644
--- a/src/secretsharing/Makefile.am
+++ b/src/secretsharing/Makefile.am
@@ -38,7 +38,9 @@ gnunet_secretsharing_profiler_DEPENDENCIES = \
gnunet_service_secretsharing_SOURCES = \
gnunet-service-secretsharing.c \
+ secretsharing_common.c \
secretsharing_protocol.h
+gnunet_service_secretsharing_CFLAGS = $(AM_CFLAGS)
gnunet_service_secretsharing_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/consensus/libgnunetconsensus.la \
@@ -49,6 +51,7 @@ gnunet_service_secretsharing_DEPENDENCIES = \
libgnunetsecretsharing_la_SOURCES = \
secretsharing_api.c \
+ secretsharing_common.c \
secretsharing.h
libgnunetsecretsharing_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
@@ -57,7 +60,8 @@ libgnunetsecretsharing_la_LDFLAGS = \
$(GN_LIB_LDFLAGS)
check_PROGRAMS = \
- test_secretsharing_api
+ test_secretsharing_api \
+ test_secretsharing_sig
if ENABLE_TEST_RUN
TESTS = $(check_PROGRAMS)
@@ -70,6 +74,12 @@ test_secretsharing_api_LDADD = \
$(top_builddir)/src/testing/libgnunettesting.la \
$(top_builddir)/src/secretsharing/libgnunetsecretsharing.la
+test_secretsharing_sig_SOURCES = \
+ test_secretsharing_sig.c \
+ secretsharing_protocol.h
+test_secretsharing_sig_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
EXTRA_DIST = \
test_secretsharing.conf
diff --git a/src/secretsharing/gnunet-secretsharing-profiler.c b/src/secretsharing/gnunet-secretsharing-profiler.c
index a9bce4a14..01eb49a2d 100755
--- a/src/secretsharing/gnunet-secretsharing-profiler.c
+++ b/src/secretsharing/gnunet-secretsharing-profiler.c
@@ -1,5 +1,319 @@
+/*
+ This file is part of GNUnet
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file secretsharing/gnunet-secretsharing-profiler.c
+ * @brief profiling tool for distributed key generation and decryption
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_secretsharing_service.h"
+#include "gnunet_testbed_service.h"
+
+static unsigned int num_peers = 3;
+
+static unsigned int threshold = 2;
+
+static struct GNUNET_TIME_Relative timeout;
+
+static struct GNUNET_SECRETSHARING_Session **session_handles;
+
+static struct GNUNET_TESTBED_Operation **testbed_operations;
+
+static unsigned int num_connected_handles;
+
+static struct GNUNET_TESTBED_Peer **peers;
+
+static struct GNUNET_PeerIdentity *peer_ids;
+
+static unsigned int num_retrieved_peer_ids;
+
+static struct GNUNET_HashCode session_id;
+
+static int verbose;
+
+
+/**
+ * Signature of the event handler function called by the
+ * respective event controller.
+ *
+ * @param cls closure
+ * @param event information about the event
+ */
+static void
+controller_cb (void *cls,
+ const struct GNUNET_TESTBED_EventInformation *event)
+{
+ GNUNET_assert (0);
+}
+
+
+/**
+ * Callback to be called when a service connect operation is completed
+ *
+ * @param cls the callback closure from functions generating an operation
+ * @param op the operation that has been finished
+ * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
+ * @param emsg error message in case the operation has failed; will be NULL if
+ * operation has executed successfully.
+ */
+static void
+connect_complete (void *cls,
+ struct GNUNET_TESTBED_Operation *op,
+ void *ca_result,
+ const char *emsg)
+{
+
+ if (NULL != emsg)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "testbed connect emsg: %s\n",
+ emsg);
+ GNUNET_assert (0);
+ }
+
+ num_connected_handles++;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "connect complete\n");
+
+ if (num_connected_handles == num_peers)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "all peers connected\n");
+ }
+}
+
+
+static void
+secret_ready_cb (void *cls,
+ const struct GNUNET_SECRETSHARING_Share *my_share,
+ const struct GNUNET_SECRETSHARING_PublicKey *public_key,
+ unsigned int num_ready_peers,
+ const struct GNUNET_PeerIdentity *ready_peers)
+{
+ struct GNUNET_SECRETSHARING_Session **sp = cls;
+ unsigned int n = sp - session_handles;
+ if (NULL == my_share || NULL == public_key)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "key generation failed for peer #%u\n", n);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "secret ready for peer #%u\n", n);
+ // FIXME: end profiler or try decryption if all secrets are ready
+}
+
+
+/**
+ * Adapter function called to establish a connection to
+ * a service.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer to connect to; will be available until
+ * GNUNET_TESTBED_operation_done() is called on the operation returned
+ * from GNUNET_TESTBED_service_connect()
+ * @return service handle to return in 'op_result', NULL on error
+ */
+static void *
+connect_adapter (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_SECRETSHARING_Session **sp = cls;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "connect adapter, %d peers\n",
+ num_peers);
+ *sp = GNUNET_SECRETSHARING_create_session (cfg,
+ num_peers,
+ peer_ids,
+ &session_id,
+ GNUNET_TIME_relative_to_absolute (timeout),
+ threshold,
+ &secret_ready_cb, sp);
+ return *sp;
+}
+
+
+/**
+ * Adapter function called to destroy a connection to
+ * a service.
+ *
+ * @param cls closure
+ * @param op_result service handle returned from the connect adapter
+ */
+static void
+disconnect_adapter(void *cls, void *op_result)
+{
+ /* FIXME: what to do here? */
+}
+
+
+/**
+ * Callback to be called when the requested peer information is available
+ *
+ * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
+ * @param op the operation this callback corresponds to
+ * @param pinfo the result; will be NULL if the operation has failed
+ * @param emsg error message if the operation has failed; will be NULL if the
+ * operation is successfull
+ */
+static void
+peer_info_cb (void *cb_cls,
+ struct GNUNET_TESTBED_Operation *op,
+ const struct GNUNET_TESTBED_PeerInformation *pinfo,
+ const char *emsg)
+{
+ struct GNUNET_PeerIdentity *p;
+ int i;
+
+ GNUNET_assert (NULL == emsg);
+
+ p = (struct GNUNET_PeerIdentity *) cb_cls;
+
+ if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY)
+ {
+ *p = *pinfo->result.id;
+ num_retrieved_peer_ids++;
+ if (num_retrieved_peer_ids == num_peers)
+ for (i = 0; i < num_peers; i++)
+ testbed_operations[i] =
+ GNUNET_TESTBED_service_connect (NULL, peers[i], "secretsharing", connect_complete, NULL,
+ connect_adapter, disconnect_adapter, &session_handles[i]);
+ }
+ else
+ {
+ GNUNET_assert (0);
+ }
+
+ GNUNET_TESTBED_operation_done (op);
+}
+
+
+/**
+ * Signature of a main function for a testcase.
+ *
+ * @param cls closure
+ * @param h the run handle
+ * @param num_peers number of peers in 'peers'
+ * @param started_peers handle to peers run in the testbed. NULL upon timeout (see
+ * GNUNET_TESTBED_test_run()).
+ * @param links_succeeded the number of overlay link connection attempts that
+ * succeeded
+ * @param links_failed the number of overlay link connection attempts that
+ * failed
+ */
+static void
+test_master (void *cls,
+ struct GNUNET_TESTBED_RunHandle *h,
+ unsigned int num_peers,
+ struct GNUNET_TESTBED_Peer **started_peers,
+ unsigned int links_succeeded,
+ unsigned int links_failed)
+{
+ int i;
+
+ GNUNET_log_setup ("gnunet-secretsharing-profiler", "INFO", NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test master\n");
+
+ peers = started_peers;
+
+ peer_ids = GNUNET_malloc (num_peers * sizeof (struct GNUNET_PeerIdentity));
+
+ session_handles = GNUNET_malloc (num_peers * sizeof (struct GNUNET_SECRETSHARING_Session *));
+ testbed_operations = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *));
+
+ for (i = 0; i < num_peers; i++)
+ GNUNET_TESTBED_peer_get_information (peers[i],
+ GNUNET_TESTBED_PIT_IDENTITY,
+ peer_info_cb,
+ &peer_ids[i]);
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ static char *session_str = "gnunet-secretsharing/test";
+ char *topology;
+ int topology_cmp_result;
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", "OVERLAY_TOPOLOGY", &topology))
+ {
+ fprintf (stderr,
+ "'OVERLAY_TOPOLOGY' not found in 'testbed' config section, "
+ "seems like you passed the wrong configuration file\n");
+ return;
+ }
+
+ topology_cmp_result = strcasecmp (topology, "NONE");
+ GNUNET_free (topology);
+
+ if (0 == topology_cmp_result)
+ {
+ fprintf (stderr,
+ "'OVERLAY_TOPOLOGY' set to 'NONE', "
+ "seems like you passed the wrong configuration file\n");
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "running gnunet-secretsharing-profiler\n");
+
+ GNUNET_CRYPTO_hash (session_str, strlen (session_str), &session_id);
+
+ (void) GNUNET_TESTBED_test_run ("gnunet-secretsharing-profiler",
+ cfgfile,
+ num_peers,
+ 0,
+ controller_cb,
+ NULL,
+ test_master,
+ NULL);
+}
+
+
int
-main ()
+main (int argc, char **argv)
{
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ { 'n', "num-peers", NULL,
+ gettext_noop ("number of peers in consensus"),
+ GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers },
+ { 't', "timeout", NULL,
+ gettext_noop ("dkg timeout"),
+ GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &timeout },
+ { 'k', "threshold", NULL,
+ gettext_noop ("threshold"),
+ GNUNET_YES, &GNUNET_GETOPT_set_uint, &threshold },
+ { 'V', "verbose", NULL,
+ gettext_noop ("be more verbose (print received values)"),
+ GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose },
+ GNUNET_GETOPT_OPTION_END
+ };
+ timeout = GNUNET_TIME_UNIT_SECONDS;
+ GNUNET_PROGRAM_run2 (argc, argv, "gnunet-secretsharing-profiler",
+ "help",
+ options, &run, NULL, GNUNET_YES);
return 0;
}
+
diff --git a/src/secretsharing/gnunet-service-secretsharing.c b/src/secretsharing/gnunet-service-secretsharing.c
index 3af899352..6c91343d5 100644
--- a/src/secretsharing/gnunet-service-secretsharing.c
+++ b/src/secretsharing/gnunet-service-secretsharing.c
@@ -26,6 +26,7 @@
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_time_lib.h"
+#include "gnunet_signatures.h"
#include "gnunet_consensus_service.h"
#include "secretsharing.h"
#include "secretsharing_protocol.h"
@@ -69,10 +70,39 @@ struct KeygenPeerInfo
gcry_mpi_t public_key_share;
/**
- * GNUNET_YES if the peer has been disqualified,
- * GNUNET_NO otherwise.
+ * Did we successfully receive the round1 element
+ * of the peer?
*/
- int disqualified;
+ int round1_valid;
+
+ /**
+ * Did we successfully receive the round1 element
+ * of the peer?
+ */
+ int round2_valid;
+};
+
+
+struct DecryptPeerInfo
+{
+ /**
+ * Identity of the peer.
+ */
+ struct GNUNET_PeerIdentity peer;
+
+ /**
+ * Original index in the key generation round.
+ * Necessary for computing the lagrange coefficients.
+ */
+ unsigned int real_index;
+
+ /**
+ * Set to the partial decryption of
+ * this peer, or NULL if we did not
+ * receive a partial decryption from this
+ * peer or the zero knowledge proof failed.
+ */
+ gcry_mpi_t partial_decryption;
};
@@ -120,6 +150,8 @@ struct KeygenSession
/**
* Minimum number of shares required to restore the secret.
+ * Also the number of coefficients for the polynomial representing
+ * the sharing. Obviously, the polynomial then has degree threshold-1.
*/
unsigned int threshold;
@@ -135,6 +167,7 @@ struct KeygenSession
/**
* Information about all participating peers.
+ * Array of size 'num_peers'.
*/
struct KeygenPeerInfo *info;
@@ -158,9 +191,18 @@ struct KeygenSession
*/
gcry_mpi_t paillier_mu;
+ /**
+ * When would we like the key to be established?
+ */
struct GNUNET_TIME_Absolute deadline;
/**
+ * When does the DKG start? Necessary to compute fractions of the
+ * operation's desired time interval.
+ */
+ struct GNUNET_TIME_Absolute start_time;
+
+ /**
* Index of the local peer in the ordered list
* of peers in the session.
*/
@@ -170,23 +212,63 @@ struct KeygenSession
struct DecryptSession
{
+ /**
+ * Decrypt sessions are stored in a linked list.
+ */
struct DecryptSession *next;
+
+ /**
+ * Decrypt sessions are stored in a linked list.
+ */
struct DecryptSession *prev;
+ /**
+ * Handle to the consensus over partial decryptions.
+ */
struct GNUNET_CONSENSUS_Handle *consensus;
+ /**
+ * Client connected to us.
+ */
struct GNUNET_SERVER_Client *client;
+
+ /**
+ * Message queue for 'client'.
+ */
+ struct GNUNET_MQ_Handle *client_mq;
+
+ /**
+ * When would we like the ciphertext to be
+ * decrypted?
+ */
+ struct GNUNET_TIME_Absolute deadline;
+
+ /**
+ * Ciphertext we want to decrypt.
+ */
+ struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
+
+ /**
+ * Share of the local peer.
+ */
+ struct GNUNET_SECRETSHARING_Share *share;
+
+ /**
+ * State information about other peers.
+ */
+ struct DecryptPeerInfo *info;
};
+
/**
* Decrypt sessions are held in a linked list.
*/
-//static struct DecryptSession *decrypt_sessions_head;
+static struct DecryptSession *decrypt_sessions_head;
/**
* Decrypt sessions are held in a linked list.
*/
-//static struct DecryptSession *decrypt_sessions_tail;
+static struct DecryptSession *decrypt_sessions_tail;
/**
* Decrypt sessions are held in a linked list.
@@ -222,6 +304,11 @@ static gcry_mpi_t elgamal_g;
static struct GNUNET_PeerIdentity my_peer;
/**
+ * Peer that runs this service.
+ */
+static struct GNUNET_CRYPTO_EddsaPrivateKey *my_peer_private_key;
+
+/**
* Configuration of this service.
*/
static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -231,20 +318,79 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
*/
static struct GNUNET_SERVER_Handle *srv;
+/**
+ * Print a field element in a fixed-size buffer.
+ */
+static void
+print_field_element (void *buf, gcry_mpi_t x)
+{
+ GNUNET_assert (0);
+}
+
+
+static struct KeygenPeerInfo *
+get_keygen_peer_info (const struct KeygenSession *ks,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ unsigned int i;
+ for (i = 0; i < ks->num_peers; i++)
+ if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
+ return &ks->info[i];
+ return NULL;
+}
+
+
+static struct DecryptPeerInfo *
+get_decrypt_peer_info (const struct DecryptSession *ds,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ unsigned int i;
+ for (i = 0; i < ds->share->num_peers; i++)
+ if (0 == memcmp (peer, &ds->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
+ return &ds->info[i];
+ return NULL;
+}
+
+
+static struct GNUNET_TIME_Absolute
+time_between (struct GNUNET_TIME_Absolute start,
+ struct GNUNET_TIME_Absolute end,
+ int num, int denum)
+{
+ struct GNUNET_TIME_Absolute result;
+ uint64_t diff;
+
+ GNUNET_assert (start.abs_value_us <= end.abs_value_us);
+ diff = end.abs_value_us - start.abs_value_us;
+ result.abs_value_us = start.abs_value_us + ((diff * num) / denum);
+
+ return result;
+}
+
/**
- * Although GNUNET_CRYPTO_hash_cmp exisits, it does not have
- * the correct signature to be used with e.g. qsort.
- * We use this function instead.
+ * Compare two peer identities. Indended to be used with qsort or bsearch.
*
- * @param h1 some hash code
- * @param h2 some hash code
- * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2.
+ * @param p1 some peer identity
+ * @param p2 some peer identity
+ * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
*/
static int
-hash_cmp (const void *h1, const void *h2)
+peer_id_cmp (const void *p1, const void *p2)
+{
+ return memcmp (p1, p2, sizeof (struct GNUNET_PeerIdentity));
+}
+
+
+int
+peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n,
+ const struct GNUNET_PeerIdentity *needle)
{
- return GNUNET_CRYPTO_hash_cmp ((struct GNUNET_HashCode *) h1, (struct GNUNET_HashCode *) h2);
+ unsigned int i;
+ for (i = 0; i < n; i++)
+ if (0 == memcmp (&haystack[i], needle, sizeof (struct GNUNET_PeerIdentity)))
+ return i;
+ return -1;
}
@@ -266,45 +412,84 @@ normalize_peers (struct GNUNET_PeerIdentity *listed,
{
unsigned int local_peer_in_list;
unsigned int n;
- unsigned int i;
struct GNUNET_PeerIdentity *normalized;
- local_peer_in_list = GNUNET_NO;
- for (i = 0; i < num_listed; i++)
+ local_peer_in_list = GNUNET_YES;
+ n = num_listed;
+ if (peer_find (listed, num_listed, &my_peer) < 0)
{
- if (0 == memcmp (&listed[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
- {
- local_peer_in_list = GNUNET_YES;
- break;
- }
+ local_peer_in_list = GNUNET_NO;
+ n += 1;
}
- n = num_listed;
- if (GNUNET_NO == local_peer_in_list)
- n++;
-
- normalized = GNUNET_malloc (n * sizeof (struct GNUNET_PeerIdentity));
+ normalized = GNUNET_new_array (n, struct GNUNET_PeerIdentity);
if (GNUNET_NO == local_peer_in_list)
normalized[n - 1] = my_peer;
memcpy (normalized, listed, num_listed * sizeof (struct GNUNET_PeerIdentity));
- qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &hash_cmp);
+ qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp);
if (NULL != my_peer_idx)
+ *my_peer_idx = peer_find (normalized, n, &my_peer);
+ if (NULL != num_normalized)
+ *num_normalized = n;
+
+ return normalized;
+}
+
+
+/**
+ * Get a the j-th lagrage coefficient for a set of indices.
+ *
+ * @param[out] coeff the lagrange coefficient
+ * @param j lagrage coefficient we want to compute
+ * @param indices indices
+ * @param num number of indices in @a indices
+ */
+static void
+compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
+ unsigned int *indices,
+ unsigned int num)
+{
+ int i;
+ /* numerator */
+ gcry_mpi_t n;
+ /* denominator */
+ gcry_mpi_t d;
+ /* temp value for l-j */
+ gcry_mpi_t tmp;
+
+ GNUNET_assert (0 != coeff);
+
+ GNUNET_assert (0 != (n = gcry_mpi_new (0)));
+ GNUNET_assert (0 != (d = gcry_mpi_new (0)));
+ GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
+
+ gcry_mpi_set_ui (n, 1);
+ gcry_mpi_set_ui (d, 1);
+
+ gcry_mpi_set_ui (coeff, 0);
+ for (i = 0; i < num; i++)
{
- for (i = 0; i < num_listed; i++)
- {
- if (0 == memcmp (&normalized[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
- {
- *my_peer_idx = i;
- break;
- }
- }
+ int l = indices[i];
+ if (l == j)
+ continue;
+ gcry_mpi_mul_ui (n, n, l);
+ // d <- d * (l-j)
+ gcry_mpi_set_ui (tmp, l);
+ gcry_mpi_sub_ui (tmp, tmp, j);
+ gcry_mpi_mul (d, d, tmp);
}
- *num_normalized = n;
- return normalized;
+ // now we do the actual division, with everything mod q, as we
+ // are not operating on elemets from <g>, but on exponents
+ GNUNET_assert (0 == gcry_mpi_invm (d, d, elgamal_q));
+ gcry_mpi_mulm (coeff, n, d, elgamal_q);
+
+ gcry_mpi_release (n);
+ gcry_mpi_release (d);
+ gcry_mpi_release (tmp);
}
@@ -433,44 +618,76 @@ generate_presecret_polynomial (struct KeygenSession *ks)
for (i = 0; i < ks->threshold; i++)
{
ks->presecret_polynomial[i] = gcry_mpi_new (PAILLIER_BITS);
+ GNUNET_assert (0 != ks->presecret_polynomial[i]);
gcry_mpi_randomize (ks->presecret_polynomial[i], PAILLIER_BITS,
GCRY_WEAK_RANDOM);
}
}
+/**
+ * Consensus element handler for round one.
+ *
+ * @param cls closure (keygen session)
+ * @param element the element from consensus
+ */
static void
keygen_round1_new_element (void *cls,
const struct GNUNET_SET_Element *element)
{
const struct GNUNET_SECRETSHARING_KeygenCommitData *d;
struct KeygenSession *ks = cls;
- unsigned int i;
+ struct KeygenPeerInfo *info;
+
+ if (NULL == element)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n");
+ return;
+ }
if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
{
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong size in consensus\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "keygen commit data with wrong size (%u) in consensus, "
+ " %u expected\n",
+ element->size, sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData));
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
+
d = element->data;
- for (i = 0; i < ks->num_peers; i++)
+ info = get_keygen_peer_info (ks, &d->peer);
+
+ if (NULL == info)
{
- if (0 == memcmp (&d->peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
- {
- // TODO: check signature
- GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].paillier_g, GCRYMPI_FMT_USG,
- &d->pubkey.g, sizeof d->pubkey.g, NULL));
- GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].paillier_n, GCRYMPI_FMT_USG,
- &d->pubkey.n, sizeof d->pubkey.n, NULL));
- GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].presecret_commitment, GCRYMPI_FMT_USG,
- &d->commitment, sizeof d->commitment, NULL));
- return;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
+ GNUNET_i2s (&d->peer));
+ return;
+ }
+
+ if (d->purpose.size !=
+ htons (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong signature purpose size in consensus\n");
+ return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity in consensus\n");
+ if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1,
+ &d->purpose, &d->signature, &d->peer.public_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n");
+ return;
+ }
+
+ GNUNET_assert (0 == gcry_mpi_scan (&info->paillier_g, GCRYMPI_FMT_USG,
+ &d->pubkey.g, sizeof d->pubkey.g, NULL));
+ GNUNET_assert (0 == gcry_mpi_scan (&info->paillier_n, GCRYMPI_FMT_USG,
+ &d->pubkey.n, sizeof d->pubkey.n, NULL));
+ GNUNET_assert (0 == gcry_mpi_scan (&info->presecret_commitment, GCRYMPI_FMT_USG,
+ &d->commitment, sizeof d->commitment, NULL));
+ info->round1_valid = GNUNET_YES;
}
@@ -505,30 +722,60 @@ keygen_round2_conclude (void *cls)
struct KeygenSession *ks = cls;
struct GNUNET_SECRETSHARING_SecretReadyMessage *m;
struct GNUNET_MQ_Envelope *ev;
+ size_t share_size;
unsigned int i;
+ unsigned int j;
+ struct GNUNET_SECRETSHARING_Share *share;
gcry_mpi_t s;
gcry_mpi_t h;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
+
GNUNET_assert (0 != (s = gcry_mpi_new (PAILLIER_BITS)));
GNUNET_assert (0 != (h = gcry_mpi_new (PAILLIER_BITS)));
// multiplicative identity
gcry_mpi_set_ui (s, 1);
+ share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
+
+ share->num_peers = 0;
+
+ for (i = 0; i < ks->num_peers; i++)
+ if (GNUNET_YES == ks->info[i].round2_valid)
+ share->num_peers++;
+
+ share->peers = GNUNET_new_array (share->num_peers, struct GNUNET_PeerIdentity);
+ share->hom_share_commitments =
+ GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement);
+ share->original_indices = GNUNET_new_array (share->num_peers, uint16_t);
+
+ j = 0;
for (i = 0; i < ks->num_peers; i++)
{
- if (GNUNET_NO == ks->info[i].disqualified)
+ if (GNUNET_YES == ks->info[i].round2_valid)
{
gcry_mpi_addm (s, s, ks->info[i].decrypted_preshare, elgamal_p);
gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p);
- // m->num_secret_peers++; // FIXME: m not initialized here!
+ share->peers[i] = ks->info[i].peer;
+ share->original_indices[i] = j++;
}
}
- ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY);
+ gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &share->my_share, PAILLIER_BITS / 8, NULL, s);
+ gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &share->public_key, PAILLIER_BITS / 8, NULL, s);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen successful with %u peers\n", share->num_peers);
+
+ m = GNUNET_malloc (sizeof (struct GNUNET_SECRETSHARING_SecretReadyMessage) +
+ ks->num_peers * sizeof (struct GNUNET_PeerIdentity));
+
+ GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
- gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &m->secret, PAILLIER_BITS / 8, NULL, s);
- gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &m->public_key, PAILLIER_BITS / 8, NULL, s);
+ ev = GNUNET_MQ_msg_extra (m, share_size,
+ GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY);
+
+ GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &m[1], share_size, NULL));
GNUNET_MQ_send (ks->client_mq, ev);
}
@@ -548,17 +795,14 @@ static void
insert_round2_element (struct KeygenSession *ks)
{
struct GNUNET_SET_Element *element;
- struct GNUNET_SECRETSHARING_KeygenRevealData *msg;
+ struct GNUNET_SECRETSHARING_KeygenRevealData *d;
unsigned char *pos;
unsigned char *last_pos;
size_t element_size;
unsigned int i;
- gcry_mpi_t c;
gcry_mpi_t idx;
gcry_mpi_t v;
- GNUNET_assert (0 != (c = gcry_mpi_new (PAILLIER_BITS)));
- // FIXME: c is never used...
GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
GNUNET_assert (0 != (idx = gcry_mpi_new (PAILLIER_BITS)));
@@ -567,13 +811,17 @@ insert_round2_element (struct KeygenSession *ks)
1 * PAILLIER_BITS / 8 * ks->threshold);
element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
+ element->size = element_size;
+ element->data = (void *) &element[1];
- msg = (void *) element->data;
- pos = (void *) &msg[1];
+ d = (void *) element->data;
+ d->peer = my_peer;
+
+ pos = (void *) &d[1];
last_pos = pos + element_size;
// exponentiated pre-shares
- for (i = 0; i <= ks->threshold; i++)
+ for (i = 0; i < ks->num_peers; i++)
{
ptrdiff_t remaining = last_pos - pos;
GNUNET_assert (remaining > 0);
@@ -586,112 +834,168 @@ insert_round2_element (struct KeygenSession *ks)
pos += PAILLIER_BITS / 8;
}
- // exponentiated coefficients
+ // encrypted pre-shares
for (i = 0; i < ks->num_peers; i++)
{
ptrdiff_t remaining = last_pos - pos;
GNUNET_assert (remaining > 0);
- gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
+ if (GNUNET_NO == ks->info[i].round1_valid)
+ gcry_mpi_set_ui (v, 0);
+ else
+ paillier_encrypt (v, ks->presecret_polynomial[0],
+ ks->info[i].paillier_g, ks->info[i].paillier_g);
gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
pos += PAILLIER_BITS / 8;
}
- // encrypted pre-shares
+ // exponentiated coefficients
for (i = 0; i < ks->threshold; i++)
{
ptrdiff_t remaining = last_pos - pos;
GNUNET_assert (remaining > 0);
- if (GNUNET_YES == ks->info[i].disqualified)
- gcry_mpi_set_ui (v, 0);
- else
- paillier_encrypt (v, ks->presecret_polynomial[0],
- ks->info[i].paillier_g, ks->info[i].paillier_g);
+ gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
pos += PAILLIER_BITS / 8;
}
+ d->purpose.size = htons (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
+ d->purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2);
+ GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature);
+
GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
- gcry_mpi_release (c);
gcry_mpi_release (v);
gcry_mpi_release (idx);
}
-static struct KeygenPeerInfo *
-get_keygen_peer_info (const struct KeygenSession *ks,
- struct GNUNET_PeerIdentity *peer)
-{
- unsigned int i;
- for (i = 0; i < ks->num_peers; i++)
- if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
- return &ks->info[i];
- return NULL;
-}
-
-
static void
keygen_round2_new_element (void *cls,
const struct GNUNET_SET_Element *element)
{
struct KeygenSession *ks = cls;
- struct GNUNET_SECRETSHARING_KeygenRevealData *msg;
+ const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
struct KeygenPeerInfo *info;
unsigned char *pos;
- unsigned char *last_pos;
gcry_mpi_t c;
+ size_t expected_element_size;
- msg = (void *) element->data;
- pos = (void *) &msg[1];
- // skip exp. pre-shares
- pos += PAILLIER_BITS / 8 * ks->num_peers;
- // skip exp. coefficients
- pos += PAILLIER_BITS / 8 * ks->threshold;
- // skip to the value for our peer
- pos += PAILLIER_BITS / 8 * ks->local_peer_idx;
+ if (NULL == element)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n");
+ return;
+ }
- last_pos = element->size + (unsigned char *) element->data;
+ expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
+ 2 * PAILLIER_BITS / 8 * ks->num_peers +
+ 1 * PAILLIER_BITS / 8 * ks->threshold);
- if ((pos >= last_pos) || ((last_pos - pos) < (PAILLIER_BITS / 8)))
+ if (element->size != expected_element_size)
{
- GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "keygen round2 data with wrong size (%u) in consensus, "
+ " %u expected\n",
+ element->size, expected_element_size);
return;
}
- GNUNET_assert (0 == gcry_mpi_scan (&c, GCRYMPI_FMT_USG,
- pos, PAILLIER_BITS / 8, NULL));
+ d = (const void *) element->data;
- info = get_keygen_peer_info (ks, &msg->peer);
+ info = get_keygen_peer_info (ks, &d->peer);
if (NULL == info)
{
- GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
+ GNUNET_i2s (&d->peer));
+ return;
+ }
+
+ if (GNUNET_NO == info->round1_valid)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "ignoring round2 element from peer with invalid round1 element (%s)\n",
+ GNUNET_i2s (&d->peer));
return;
}
+ if (GNUNET_YES == info->round2_valid)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "ignoring duplicate round2 element (%s)\n",
+ GNUNET_i2s (&d->peer));
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
+
+
+ pos = (void *) &d[1];
+ // skip exponentiated pre-shares
+ pos += PAILLIER_BITS / 8 * ks->num_peers;
+ // skip encrypted pre-shares
+ pos += PAILLIER_BITS / 8 * ks->num_peers;
+ // the first exponentiated coefficient is the public key share
+ GNUNET_assert (0 == gcry_mpi_scan (&info->public_key_share, GCRYMPI_FMT_USG,
+ pos, PAILLIER_BITS / 8, NULL));
+
+ pos = (void *) &d[1];
+ // skip exp. pre-shares
+ pos += PAILLIER_BITS / 8 * ks->num_peers;
+ // skip to the encrypted value for our peer
+ pos += PAILLIER_BITS / 8 * ks->local_peer_idx;
+
+ GNUNET_assert (0 == gcry_mpi_scan (&c, GCRYMPI_FMT_USG,
+ pos, PAILLIER_BITS / 8, NULL));
+
+ GNUNET_assert (0 != (info->decrypted_preshare = mpi_new (0)));
+
paillier_decrypt (info->decrypted_preshare, c, ks->paillier_lambda, ks->paillier_mu,
ks->info[ks->local_peer_idx].paillier_n);
- // TODO: validate signature and proofs
+ // TODO: validate zero knowledge proofs
+
+ if (d->purpose.size !=
+ htons (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n");
+ return;
+ }
+ if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2,
+ &d->purpose, &d->signature, &d->peer.public_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n");
+ return;
+ }
+
+ info->round2_valid = GNUNET_YES;
}
+/**
+ * Called when the first consensus round has concluded.
+ * Will initiate the second round.
+ *
+ * @param cls closure
+ */
static void
keygen_round1_conclude (void *cls)
{
struct KeygenSession *ks = cls;
- // TODO: destroy old consensus
- // TODO: mark peers without keys as disqualified
+ GNUNET_CONSENSUS_destroy (ks->consensus);
ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
keygen_round2_new_element, ks);
insert_round2_element (ks);
- GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round2_conclude, ks);
+ GNUNET_CONSENSUS_conclude (ks->consensus,
+ /* last round, thus conclude at DKG deadline */
+ ks->deadline,
+ keygen_round2_conclude,
+ ks);
}
@@ -716,6 +1020,8 @@ insert_round1_element (struct KeygenSession *ks)
element->data = d;
element->size = sizeof *d;
+ d->peer = my_peer;
+
GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
@@ -734,9 +1040,9 @@ insert_round1_element (struct KeygenSession *ks)
(unsigned char *) d->pubkey.n, PAILLIER_BITS / 8, NULL,
ks->info[ks->local_peer_idx].paillier_n));
- // FIXME: sign stuff
-
- d->peer = my_peer;
+ d->purpose.size = htons ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
+ d->purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
+ GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature));
GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
}
@@ -758,13 +1064,19 @@ static void handle_client_keygen (void *cls,
const struct GNUNET_SECRETSHARING_CreateMessage *msg =
(const struct GNUNET_SECRETSHARING_CreateMessage *) message;
struct KeygenSession *ks;
+ unsigned int i;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n");
ks = GNUNET_new (struct KeygenSession);
+ /* FIXME: check if client already has some session */
+
GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks);
+ ks->client = client;
+ ks->client_mq = GNUNET_MQ_queue_for_server_client (client);
+
ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
ks->threshold = ntohs (msg->threshold);
ks->num_peers = ntohs (msg->num_peers);
@@ -772,11 +1084,21 @@ static void handle_client_keygen (void *cls,
ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers,
&ks->num_peers, &ks->local_peer_idx);
- // TODO: initialize MPIs in peer structure
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "first round of consensus with %u peers\n", ks->num_peers);
ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id,
keygen_round1_new_element, ks);
+ ks->info = GNUNET_malloc (ks->num_peers * sizeof (struct KeygenPeerInfo));
+
+ for (i = 0; i < ks->num_peers; i++)
+ ks->info[i].peer = ks->peers[i];
+
+ GNUNET_assert (0 != (ks->info[ks->local_peer_idx].paillier_g = mpi_new (0)));
+ GNUNET_assert (0 != (ks->info[ks->local_peer_idx].paillier_n = mpi_new (0)));
+ GNUNET_assert (0 != (ks->paillier_lambda = mpi_new (0)));
+ GNUNET_assert (0 != (ks->paillier_mu = mpi_new (0)));
+
paillier_create (ks->info[ks->local_peer_idx].paillier_g,
ks->info[ks->local_peer_idx].paillier_n,
ks->paillier_lambda,
@@ -787,7 +1109,149 @@ static void handle_client_keygen (void *cls,
insert_round1_element (ks);
- GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round1_conclude, ks);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "starting conclude of round 1\n");
+
+ GNUNET_CONSENSUS_conclude (ks->consensus,
+ /* half the overall time */
+ time_between (ks->start_time, ks->deadline, 1, 2),
+ keygen_round1_conclude,
+ ks);
+
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Called when the partial decryption consensus concludes.
+ */
+static void
+decrypt_conclude (void *cls)
+{
+ struct DecryptSession *ds = cls;
+ struct GNUNET_SECRETSHARING_DecryptResponseMessage *msg;
+ struct GNUNET_MQ_Envelope *ev;
+ gcry_mpi_t lagrange;
+ gcry_mpi_t m;
+ gcry_mpi_t tmp;
+ gcry_mpi_t c_2;
+ unsigned int *indices;
+ unsigned int num;
+ unsigned int i;
+ unsigned int j;
+
+ GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
+ GNUNET_assert (0 != (m = gcry_mpi_new (0)));
+ GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
+
+ num = 0;
+ for (i = 0; i < ds->share->num_peers; i++)
+ if (NULL != ds->info[i].partial_decryption)
+ num++;
+
+ indices = GNUNET_malloc (num * sizeof (unsigned int));
+ j = 0;
+ for (i = 0; i < ds->share->num_peers; i++)
+ if (NULL != ds->info[i].partial_decryption)
+ indices[j++] = ds->info[i].real_index;
+
+ gcry_mpi_set_ui (m, 1);
+
+ for (i = 0; i < num; i++)
+ {
+ compute_lagrange_coefficient (lagrange, indices[i], indices, num);
+ // w_j^{\lambda_j}
+ gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p);
+ gcry_mpi_mulm (m, m, tmp, elgamal_p);
+ }
+
+ GNUNET_assert (0 == gcry_mpi_scan (&c_2, GCRYMPI_FMT_USG, ds->ciphertext.c2_bits,
+ PAILLIER_BITS / 8, NULL));
+
+ // m <- c_2 / m
+ gcry_mpi_invm (m, m, elgamal_p);
+ gcry_mpi_mulm (m, c_2, m, elgamal_p);
+
+ ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE);
+ print_field_element (&msg->plaintext, m);
+ msg->success = htonl (1);
+ GNUNET_MQ_send (ds->client_mq, ev);
+
+ // FIXME: what if not enough peers participated?
+}
+
+
+/**
+ * Called when a new partial decryption arrives.
+ */
+static void
+decrypt_new_element (void *cls,
+ const struct GNUNET_SET_Element *element)
+{
+ struct DecryptSession *session = cls;
+ const struct GNUNET_SECRETSHARING_DecryptData *d;
+ struct DecryptPeerInfo *info;
+
+ if (NULL == element)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
+ /* FIXME: destroy */
+ return;
+ }
+
+ if (element->size != sizeof *d)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element of wrong size in decrypt consensus\n");
+ return;
+ }
+
+ d = element->data;
+
+ info = get_decrypt_peer_info (session, &d->peer);
+
+ if (NULL == info)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element from invalid peer (%s)\n",
+ GNUNET_i2s (&d->peer));
+ return;
+ }
+
+ if (NULL != info->partial_decryption)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n",
+ GNUNET_i2s (&d->peer));
+ return;
+ }
+
+ // FIXME: check NIZP first
+
+ GNUNET_assert (0 == gcry_mpi_scan (&info->partial_decryption,
+ GCRYMPI_FMT_USG, &d->partial_decryption, PAILLIER_BITS / 8, NULL));
+}
+
+static void
+insert_decrypt_element (struct DecryptSession *ds)
+{
+ struct GNUNET_SECRETSHARING_DecryptData d;
+ struct GNUNET_SET_Element element;
+ gcry_mpi_t x;
+ gcry_mpi_t s;
+
+ GNUNET_assert (0 == gcry_mpi_scan (&x, GCRYMPI_FMT_USG, ds->ciphertext.c1_bits, PAILLIER_BITS / 8, NULL));
+ GNUNET_assert (0 == gcry_mpi_scan (&s, GCRYMPI_FMT_USG, &ds->share->my_share, PAILLIER_BITS / 8, NULL));
+
+ gcry_mpi_powm (x, x, s, elgamal_p);
+
+ element.data = (void *) &d;
+ element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
+
+ d.peer = my_peer;
+ d.purpose.size = htons (element.size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
+ d.purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
+ GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature);
+
+ print_field_element (&d.partial_decryption, x);
+
+ GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
}
@@ -800,11 +1264,80 @@ static void handle_client_keygen (void *cls,
* @param message the actual message
*/
static void handle_client_decrypt (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader
- *message)
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader
+ *message)
{
- GNUNET_assert (0);
+ const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg =
+ (const void *) message;
+ struct DecryptSession *ds;
+ struct GNUNET_HashCode session_id;
+
+ ds = GNUNET_new (struct DecryptSession);
+ // FIXME: check if session already exists
+ GNUNET_CONTAINER_DLL_insert (decrypt_sessions_head, decrypt_sessions_tail, ds);
+ ds->client = client;
+ ds->client_mq = GNUNET_MQ_queue_for_server_client (client);
+ ds->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
+ ds->ciphertext = msg->ciphertext;
+
+ ds->share = GNUNET_SECRETSHARING_share_read (&msg[1], ntohs (msg->header.size) - sizeof *msg, NULL);
+ // FIXME: probably should be break rather than assert
+ GNUNET_assert (NULL != ds->share);
+
+ // FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ...
+ GNUNET_CRYPTO_hash (&msg->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext), &session_id);
+
+ ds->consensus = GNUNET_CONSENSUS_create (cfg,
+ ds->share->num_peers,
+ ds->share->peers,
+ &session_id,
+ decrypt_new_element,
+ ds);
+
+ insert_decrypt_element (ds);
+
+ GNUNET_CONSENSUS_conclude (ds->consensus, ds->deadline, decrypt_conclude, ds);
+}
+
+
+static void
+init_crypto_constants (void)
+{
+ /* 1024-bit safe prime */
+ const char *elgamal_p_hex =
+ "0x08a347d3d69e8b2dd7d1b12a08dfbccbebf4ca"
+ "6f4269a0814e158a34312964d946b3ef22882317"
+ "2bcf30fc08f772774cb404f9bc002a6f66b09a79"
+ "d810d67c4f8cb3bedc6060e3c8ef874b1b64df71"
+ "6c7d2b002da880e269438d5a776e6b5f253c8df5"
+ "6a16b1c7ce58def07c03db48238aadfc52a354a2"
+ "7ed285b0c1675cad3f3";
+ /* 1023-bit Sophie Germain prime, q = (p-1)/2 */
+ const char *elgamal_q_hex =
+ "0x0451a3e9eb4f4596ebe8d895046fde65f5fa65"
+ "37a134d040a70ac51a1894b26ca359f79144118b"
+ "95e7987e047bb93ba65a027cde001537b3584d3c"
+ "ec086b3e27c659df6e303071e477c3a58db26fb8"
+ "b63e958016d4407134a1c6ad3bb735af929e46fa"
+ "b50b58e3e72c6f783e01eda411c556fe2951aa51"
+ "3f6942d860b3ae569f9";
+ /* generator of the unique size q subgroup of Z_p^* */
+ const char *elgamal_g_hex =
+ "0x05c00c36d2e822950087ef09d8252994adc4e4"
+ "8fe3ec70269f035b46063aff0c99b633fd64df43"
+ "02442e1914c829a41505a275438871f365e91c12"
+ "3d5303ef9e90f4b8cb89bf86cc9b513e74a72634"
+ "9cfd9f953674fab5d511e1c078fc72d72b34086f"
+ "c82b4b951989eb85325cb203ff98df76bc366bba"
+ "1d7024c3650f60d0da";
+
+ GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
+ elgamal_q_hex, 0, NULL));
+ GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
+ elgamal_p_hex, 0, NULL));
+ GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
+ elgamal_g_hex, 0, NULL));
}
@@ -826,6 +1359,15 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
};
cfg = c;
srv = server;
+ my_peer_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
+ if (NULL == my_peer_private_key)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not access host private key\n");
+ GNUNET_break (0);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ init_crypto_constants ();
if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
diff --git a/src/secretsharing/secretsharing.h b/src/secretsharing/secretsharing.h
index 0af21028d..232721410 100644
--- a/src/secretsharing/secretsharing.h
+++ b/src/secretsharing/secretsharing.h
@@ -27,13 +27,22 @@
#define SECRETSHARING_H
#include "platform.h"
-#include "gnunet_common.h"
+#include "gnunet_util_lib.h"
#include "gnunet_time_lib.h"
+#include "gnunet_common.h"
#include "gnunet_secretsharing_service.h"
GNUNET_NETWORK_STRUCT_BEGIN
+struct GNUNET_SECRETSHARING_FieldElement
+{
+ /**
+ * Value of an element in <elgamal_g>.
+ */
+ unsigned char bits[GNUNET_SECRETSHARING_KEY_BITS / 8];
+};
+
struct GNUNET_SECRETSHARING_CreateMessage
{
@@ -67,31 +76,46 @@ struct GNUNET_SECRETSHARING_CreateMessage
};
-struct GNUNET_SECRETSHARING_SecretReadyMessage
+
+struct GNUNET_SECRETSHARING_ShareHeaderNBO
{
/**
- * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY
+ * Threshold for the key this share belongs to.
*/
- struct GNUNET_MessageHeader header;
+ uint16_t threshold;
+
+ /**
+ * Peers that have the share.
+ */
+ uint16_t num_peers;
/**
- * Secret share in network byte order.
+ * Index of our peer in the list.
*/
- unsigned char secret[GNUNET_SECRETSHARING_KEY_BITS / 8];
+ uint16_t my_peer;
/**
- * Secret share in network byte order.
+ * Public key. Must correspond to the product of
+ * the homomorphic share commitments.
*/
struct GNUNET_SECRETSHARING_PublicKey public_key;
/**
- * Number of peers at the end of this message.
- * Includes peers that are part of the established
- * threshold crypto system.
+ * Share of 'my_peer'
*/
- uint16_t num_secret_peers GNUNET_PACKED;
+ struct GNUNET_SECRETSHARING_FieldElement my_share;
+};
+
+
+struct GNUNET_SECRETSHARING_SecretReadyMessage
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY
+ */
+ struct GNUNET_MessageHeader header;
+
+ /* rest: the serialized share */
- /* struct GNUNET_PeerIdentity[num_peers]; */
};
@@ -103,35 +127,88 @@ struct GNUNET_SECRETSHARING_DecryptRequestMessage
struct GNUNET_MessageHeader header;
/**
- * Ciphertext to request decryption for.
+ * Until when should the decryption be finished?
*/
- unsigned char ciphertext[GNUNET_SECRETSHARING_KEY_BITS / 8];
+ struct GNUNET_TIME_AbsoluteNBO deadline;
/**
- * Number of peers at the end of this message.
- * Includes peers that are part of the established
- * threshold crypto system.
+ * Ciphertext we want to decrypt.
*/
- uint16_t num_secret_peers GNUNET_PACKED;
+ struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
- /* struct GNUNET_PeerIdentity[num_peers]; */
+ /* the share with payload */
};
struct GNUNET_SECRETSHARING_DecryptResponseMessage
{
/**
- * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_RESPONSE
+ * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE
*/
struct GNUNET_MessageHeader header;
/**
- * Ciphertext to request decryption for.
+ * Zero if decryption failed, non-zero if decryption succeeded.
+ * If the decryption failed, plaintext is also zero.
*/
- unsigned char plaintext[GNUNET_SECRETSHARING_KEY_BITS / 8];
+ uint32_t success;
+
+ /**
+ * Decrypted plaintext.
+ */
+ struct GNUNET_SECRETSHARING_FieldElement plaintext;
};
GNUNET_NETWORK_STRUCT_END
+
+/**
+ * A share, with all values in in host byte order.
+ */
+struct GNUNET_SECRETSHARING_Share
+{
+ /**
+ * Threshold for the key this share belongs to.
+ */
+ uint16_t threshold;
+
+ /**
+ * Peers that have the share.
+ */
+ uint16_t num_peers;
+
+ /**
+ * Index of our peer in the list.
+ */
+ uint16_t my_peer;
+
+ /**
+ * Public key. Must correspond to the product of
+ * the homomorphic share commitments.
+ */
+ struct GNUNET_SECRETSHARING_PublicKey public_key;
+
+ /**
+ * Share of 'my_peer'
+ */
+ struct GNUNET_SECRETSHARING_FieldElement my_share;
+
+ /**
+ * Peer identities (includes 'my_peer')
+ */
+ struct GNUNET_PeerIdentity *peers;
+
+ /*
+ * Homomorphic commitments to each peer's share (includes 'my_peer')
+ */
+ struct GNUNET_SECRETSHARING_FieldElement *hom_share_commitments;
+
+ /*
+ * Original indices of peers from the DKG round.
+ */
+ uint16_t *original_indices;
+};
+
+
#endif
diff --git a/src/secretsharing/secretsharing_api.c b/src/secretsharing/secretsharing_api.c
index a44fa2a2f..d2b53acc7 100644
--- a/src/secretsharing/secretsharing_api.c
+++ b/src/secretsharing/secretsharing_api.c
@@ -31,8 +31,6 @@
#define LOG(kind,...) GNUNET_log_from (kind, "secretsharing-api",__VA_ARGS__)
-
-
/**
* Session that will eventually establish a shared secred between
* the involved peers and allow encryption and cooperative decryption.
@@ -61,6 +59,30 @@ struct GNUNET_SECRETSHARING_Session
};
+struct GNUNET_SECRETSHARING_DecryptionHandle
+{
+ /**
+ * Client connected to the secretsharing service.
+ */
+ struct GNUNET_CLIENT_Connection *client;
+
+ /**
+ * Message queue for 'client'.
+ */
+ struct GNUNET_MQ_Handle *mq;
+
+ /**
+ * Called when the secret sharing is done.
+ */
+ GNUNET_SECRETSHARING_DecryptCallback decrypt_cb;
+
+ /**
+ * Closure for 'decrypt_cb'.
+ */
+ void *decrypt_cls;
+};
+
+
static void
handle_session_client_error (void *cls, enum GNUNET_MQ_Error error)
{
@@ -69,16 +91,29 @@ handle_session_client_error (void *cls, enum GNUNET_MQ_Error error)
s->secret_ready_cb (s->secret_ready_cls, NULL, NULL, 0, NULL);
}
+
+static void
+handle_decrypt_client_error (void *cls, enum GNUNET_MQ_Error error)
+{
+ GNUNET_assert (0);
+}
+
static void
handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg)
{
- struct GNUNET_SECRETSHARING_Session *s = cls;
+ struct GNUNET_SECRETSHARING_Session *session = cls;
+ struct GNUNET_SECRETSHARING_Share *share;
const struct GNUNET_SECRETSHARING_SecretReadyMessage *m = (const void *) msg;
+ size_t share_size;
+
+ share_size = ntohs (m->header.size) - sizeof *m;
+
+ share = GNUNET_SECRETSHARING_share_read (&m[1], share_size, NULL);
- s->secret_ready_cb (s->secret_ready_cls,
- NULL,
- &m->public_key,
- ntohs (m->num_secret_peers),
+ session->secret_ready_cb (session->secret_ready_cls,
+ share, /* FIXME */
+ &share->public_key,
+ share->num_peers,
(struct GNUNET_PeerIdentity *) &m[1]);
}
@@ -113,14 +148,86 @@ GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *c
handle_session_client_error, s);
GNUNET_assert (NULL != s->mq);
- ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE);
+ ev = GNUNET_MQ_msg_extra (msg,
+ num_peers * sizeof (struct GNUNET_PeerIdentity),
+ GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE);
+
msg->threshold = htons (threshold);
+ msg->num_peers = htons (num_peers);
+ msg->session_id = *session_id;
+ msg->deadline = GNUNET_TIME_absolute_hton (deadline);
+ memcpy (&msg[1], peers, num_peers * sizeof (struct GNUNET_PeerIdentity));
+
GNUNET_MQ_send (s->mq, ev);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "secretsharing session created\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "secretsharing session created with %u peers\n",
+ num_peers);
return s;
+}
+
+static void
+handle_decrypt_done (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+ GNUNET_assert (0);
}
+/**
+ * Publish the given ciphertext for decryption. Once a sufficient (>=k) number of peers has
+ * published the same value, it will be decrypted.
+ *
+ * When the operation is canceled, the decrypt_cb is not called anymore, but the calling
+ * peer may already have irrevocably contributed his share for the decryption of the value.
+ *
+ * @param share our secret share to use for decryption
+ * @param ciphertext ciphertext to publish in order to decrypt it (if enough peers agree)
+ * @param decrypt_cb callback called once the decryption succeeded
+ * @param decrypt_cb_cls closure for @a decrypt_cb
+ * @return handle to cancel the operation
+ */
+struct GNUNET_SECRETSHARING_DecryptionHandle *
+GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_SECRETSHARING_Share *share,
+ struct GNUNET_SECRETSHARING_Ciphertext *ciphertext,
+ struct GNUNET_TIME_Absolute deadline,
+ GNUNET_SECRETSHARING_DecryptCallback decrypt_cb,
+ void *decrypt_cb_cls)
+{
+ struct GNUNET_SECRETSHARING_DecryptionHandle *s;
+ struct GNUNET_MQ_Envelope *ev;
+ struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg;
+ static const struct GNUNET_MQ_MessageHandler mq_handlers[] = {
+ {handle_decrypt_done, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE, 0},
+ GNUNET_MQ_HANDLERS_END
+ };
+ size_t share_size;
+
+
+ s = GNUNET_new (struct GNUNET_SECRETSHARING_DecryptionHandle);
+ s->client = GNUNET_CLIENT_connect ("secretsharing", cfg);
+ s->decrypt_cb = decrypt_cb;
+ s->decrypt_cls = decrypt_cb_cls;
+ GNUNET_assert (NULL != s->client);
+
+ s->mq = GNUNET_MQ_queue_for_connection_client (s->client, mq_handlers,
+ handle_decrypt_client_error, s);
+ GNUNET_assert (NULL != s->mq);
+
+ GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
+
+ ev = GNUNET_MQ_msg_extra (msg,
+ share_size,
+ GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT);
+
+ GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &msg[1], share_size, NULL));
+
+ msg->deadline = GNUNET_TIME_absolute_hton (deadline);
+
+ GNUNET_MQ_send (s->mq, ev);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "decrypt session created\n");
+ return s;
+}
+
diff --git a/src/secretsharing/secretsharing_protocol.h b/src/secretsharing/secretsharing_protocol.h
index 470002f10..3778ade41 100644
--- a/src/secretsharing/secretsharing_protocol.h
+++ b/src/secretsharing/secretsharing_protocol.h
@@ -31,6 +31,7 @@
#include "platform.h"
#include "gnunet_common.h"
#include "gnunet_protocols.h"
+#include "secretsharing.h"
/**
* Bit length used for the Paillier crypto system.
@@ -113,6 +114,50 @@ struct GNUNET_SECRETSHARING_KeygenRevealData
/* values follow */
};
+
+/**
+ * Data of then element put in consensus
+ * for decrypting a value.
+ */
+struct GNUNET_SECRETSHARING_DecryptData
+{
+ /*
+ * Signature over rest of the message.
+ */
+ struct GNUNET_CRYPTO_EddsaSignature signature;
+ /*
+ * Signature purpose for signing the keygen commit data.
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+ /**
+ * Ciphertext we want to decrypt.
+ */
+ struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
+ /**
+ * Peer that inserts this element.
+ */
+ struct GNUNET_PeerIdentity peer;
+ /**
+ * Partial decryption, computed as c_1^{s_i}
+ */
+ struct GNUNET_SECRETSHARING_FieldElement partial_decryption;
+ /**
+ * Commitment for the non-interactive zero knowledge proof.
+ * g^\beta, with \beta < q
+ */
+ struct GNUNET_SECRETSHARING_FieldElement nizk_commit1;
+ /**
+ * Commitment for the non-interactive zero knowledge proof.
+ * c_1^\beta, with \beta < q
+ */
+ struct GNUNET_SECRETSHARING_FieldElement nizk_commit2;
+ /**
+ * Reponse to the challenge computed from the protocol transcript.
+ * r = \beta + challenge \cdot share_i
+ */
+ struct GNUNET_SECRETSHARING_FieldElement nizk_response;
+};
+
GNUNET_NETWORK_STRUCT_END
#endif
diff --git a/src/secretsharing/test_secretsharing.conf b/src/secretsharing/test_secretsharing.conf
index e69de29bb..9cbb95608 100644
--- a/src/secretsharing/test_secretsharing.conf
+++ b/src/secretsharing/test_secretsharing.conf
@@ -0,0 +1,36 @@
+[secretsharing]
+AUTOSTART = YES
+PREFIX = valgrind
+
+[consensus]
+AUTOSTART = YES
+
+[transport]
+OPTIONS = -LERROR
+
+[arm]
+DEFAULTSERVICES = core consensus set secretsharing
+
+[set]
+OPTIONS = -L INFO
+#PREFIX = valgrind --leak-check=full
+
+[testbed]
+OVERLAY_TOPOLOGY = CLIQUE
+
+[hostlist]
+SERVERS =
+
+[nat]
+# Use addresses from the local network interfaces (inluding loopback, but also others)
+USE_LOCALADDR = YES
+
+# Disable IPv6 support
+DISABLEV6 = NO
+
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = YES
+
+[nse]
+AUTOSTART = NO
+
diff --git a/src/secretsharing/test_secretsharing_sig.c b/src/secretsharing/test_secretsharing_sig.c
new file mode 100644
index 000000000..da5f0a390
--- /dev/null
+++ b/src/secretsharing/test_secretsharing_sig.c
@@ -0,0 +1,45 @@
+/*
+ This file is part of GNUnet.
+ (C) 2013 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file secretsharing/test_secretsharing_sig.c
+ * @brief ...
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "secretsharing_protocol.h"
+
+
+int
+main (int argc, char **argv)
+{
+ struct GNUNET_SECRETSHARING_KeygenCommitData *d;
+ struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
+
+ private_key = GNUNET_CRYPTO_eddsa_key_create ();
+
+ d = GNUNET_malloc (sizeof *d);
+ d->purpose.size = htons ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
+ d->purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
+ GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (private_key, &d->purpose, &d->signature));
+ return 0;
+}
+