aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2014-02-11 00:09:53 +0000
committerFlorian Dold <florian.dold@gmail.com>2014-02-11 00:09:53 +0000
commit3e6c5eb76deedb76715e68e215622bcdd4eba3bf (patch)
tree6547309ea76a9daadfbedc04a0147b87340470d7 /src
parent48177fb73301df925712f5237ca71bb0a5088152 (diff)
downloadgnunet-3e6c5eb76deedb76715e68e215622bcdd4eba3bf.tar.gz
gnunet-3e6c5eb76deedb76715e68e215622bcdd4eba3bf.zip
- fixed wrong crypto in secretsharing
- added zero knowledge proofs (except the one for fair encryption) and other verifications
Diffstat (limited to 'src')
-rw-r--r--src/secretsharing/gnunet-service-secretsharing.c417
-rw-r--r--src/secretsharing/secretsharing.h9
-rw-r--r--src/secretsharing/secretsharing_common.c6
-rw-r--r--src/secretsharing/test_secretsharing.conf2
4 files changed, 370 insertions, 64 deletions
diff --git a/src/secretsharing/gnunet-service-secretsharing.c b/src/secretsharing/gnunet-service-secretsharing.c
index b29433824..435c10b2b 100644
--- a/src/secretsharing/gnunet-service-secretsharing.c
+++ b/src/secretsharing/gnunet-service-secretsharing.c
@@ -58,15 +58,15 @@ struct KeygenPeerInfo
58 gcry_mpi_t presecret_commitment; 58 gcry_mpi_t presecret_commitment;
59 59
60 /** 60 /**
61 * The peer's preshare that we decrypted 61 * Commitment to the preshare that is
62 * with out private key. 62 * intended for our peer.
63 */ 63 */
64 gcry_mpi_t decrypted_preshare; 64 gcry_mpi_t preshare_commitment;
65 65
66 /** 66 /**
67 * Multiplicative share of the public key. 67 * Sigma (exponentiated share) for this peer.
68 */ 68 */
69 gcry_mpi_t public_key_share; 69 gcry_mpi_t sigma;
70 70
71 /** 71 /**
72 * Did we successfully receive the round1 element 72 * Did we successfully receive the round1 element
@@ -204,6 +204,17 @@ struct KeygenSession
204 * of peers in the session. 204 * of peers in the session.
205 */ 205 */
206 unsigned int local_peer_idx; 206 unsigned int local_peer_idx;
207
208 /**
209 * Share of our peer. Once preshares from other peers are received, they
210 * will be added to 'my'share.
211 */
212 gcry_mpi_t my_share;
213
214 /**
215 * Public key, will be updated when a round2 element arrives.
216 */
217 gcry_mpi_t public_key;
207}; 218};
208 219
209 220
@@ -593,6 +604,7 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
593} 604}
594 605
595 606
607
596/** 608/**
597 * Generate the random coefficients of our pre-secret polynomial 609 * Generate the random coefficients of our pre-secret polynomial
598 * 610 *
@@ -679,8 +691,7 @@ keygen_round1_new_element (void *cls,
679 return; 691 return;
680 } 692 }
681 info->paillier_public_key = d->pubkey; 693 info->paillier_public_key = d->pubkey;
682 // FIXME: does not make any sense / is wrong 694 GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->commitment, 512 / 8);
683 GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->pubkey.n, GNUNET_CRYPTO_PAILLIER_BITS / 8);
684 info->round1_valid = GNUNET_YES; 695 info->round1_valid = GNUNET_YES;
685} 696}
686 697
@@ -720,21 +731,9 @@ keygen_round2_conclude (void *cls)
720 unsigned int i; 731 unsigned int i;
721 unsigned int j; 732 unsigned int j;
722 struct GNUNET_SECRETSHARING_Share *share; 733 struct GNUNET_SECRETSHARING_Share *share;
723 /* our share */
724 gcry_mpi_t s;
725 /* public key */
726 gcry_mpi_t h;
727 734
728 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n"); 735 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
729 736
730 GNUNET_assert (0 != (s = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
731 GNUNET_assert (0 != (h = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
732
733 // multiplicative identity
734 gcry_mpi_set_ui (h, 1);
735 // additive identity
736 gcry_mpi_set_ui (s, 0);
737
738 share = GNUNET_new (struct GNUNET_SECRETSHARING_Share); 737 share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
739 738
740 share->num_peers = 0; 739 share->num_peers = 0;
@@ -744,29 +743,38 @@ keygen_round2_conclude (void *cls)
744 share->num_peers++; 743 share->num_peers++;
745 744
746 share->peers = GNUNET_new_array (share->num_peers, struct GNUNET_PeerIdentity); 745 share->peers = GNUNET_new_array (share->num_peers, struct GNUNET_PeerIdentity);
747 share->hom_share_commitments = 746 share->sigmas =
748 GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement); 747 GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement);
749 share->original_indices = GNUNET_new_array (share->num_peers, uint16_t); 748 share->original_indices = GNUNET_new_array (share->num_peers, uint16_t);
750 749
751 /* maybe we're not even in the list of peers? */ 750 /* maybe we're not even in the list of peers? */
752 share->my_peer = share->num_peers; 751 share->my_peer = share->num_peers;
753 752
754 j = 0; 753 j = 0; /* running index of valid peers */
755 for (i = 0; i < ks->num_peers; i++) 754 for (i = 0; i < ks->num_peers; i++)
756 { 755 {
757 if (GNUNET_YES == ks->info[i].round2_valid) 756 if (GNUNET_YES == ks->info[i].round2_valid)
758 { 757 {
759 gcry_mpi_addm (s, s, ks->info[i].decrypted_preshare, elgamal_p); 758 share->peers[j] = ks->info[i].peer;
760 gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p); 759 GNUNET_CRYPTO_mpi_print_unsigned (&share->sigmas[j],
761 share->peers[i] = ks->info[i].peer; 760 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
762 share->original_indices[i] = j++; 761 ks->info[i].sigma);
762 share->original_indices[i] = j;
763 if (0 == memcmp (&share->peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity))) 763 if (0 == memcmp (&share->peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
764 share->my_peer = i; 764 share->my_peer = j;
765 j += 1;
765 } 766 }
766 } 767 }
767 768
768 GNUNET_CRYPTO_mpi_print_unsigned (&share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, s); 769 if (share->my_peer == share->num_peers)
769 GNUNET_CRYPTO_mpi_print_unsigned (&share->public_key, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, h); 770 {
771 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: peer identity not in share\n", ks->local_peer_idx);
772 }
773
774 GNUNET_CRYPTO_mpi_print_unsigned (&share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
775 ks->my_share);
776 GNUNET_CRYPTO_mpi_print_unsigned (&share->public_key, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
777 ks->public_key);
770 778
771 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers); 779 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers);
772 780
@@ -792,8 +800,8 @@ keygen_round2_conclude (void *cls)
792 * (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}} 800 * (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}}
793 * (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}} 801 * (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}}
794 * (3) The encrypted pre-shares Y_{i,j} 802 * (3) The encrypted pre-shares Y_{i,j}
795 * (4) The zero knowledge proof for correctness of 803 * (4) The zero knowledge proof for fairness of
796 * the encryption 804 * the encryption
797 * 805 *
798 * @param ks session to use 806 * @param ks session to use
799 */ 807 */
@@ -899,6 +907,67 @@ insert_round2_element (struct KeygenSession *ks)
899} 907}
900 908
901 909
910static gcry_mpi_t
911keygen_reveal_get_exp_preshare (struct KeygenSession *ks,
912 const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
913 unsigned int idx)
914{
915 unsigned char *pos;
916 gcry_mpi_t exp_preshare;
917
918 GNUNET_assert (idx < ks->num_peers);
919
920 GNUNET_assert (NULL != (exp_preshare = gcry_mpi_new (0)));
921
922 pos = (void *) &d[1];
923 // skip exponentiated pre-shares we don't want
924 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * idx;
925 GNUNET_CRYPTO_mpi_scan_unsigned (&exp_preshare, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
926 return exp_preshare;
927}
928
929static gcry_mpi_t
930keygen_reveal_get_exp_coeff (struct KeygenSession *ks,
931 const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
932 unsigned int idx)
933{
934 unsigned char *pos;
935 gcry_mpi_t exp_coeff;
936
937 GNUNET_assert (idx < ks->threshold);
938 GNUNET_assert (NULL != (exp_coeff = gcry_mpi_new (0)));
939
940 pos = (void *) &d[1];
941 // skip exponentiated pre-shares
942 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
943 // skip encrypted pre-shares
944 pos += sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * ks->num_peers;
945 // skip exp. coeffs we are not interested in
946 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * idx;
947 // the first exponentiated coefficient is the public key share
948 GNUNET_CRYPTO_mpi_scan_unsigned (&exp_coeff, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
949 return exp_coeff;
950}
951
952
953static struct GNUNET_CRYPTO_PaillierCiphertext *
954keygen_reveal_get_enc_preshare (struct KeygenSession *ks,
955 const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
956 unsigned int idx)
957{
958 unsigned char *pos;
959
960 GNUNET_assert (idx < ks->num_peers);
961
962 pos = (void *) &d[1];
963 // skip exponentiated pre-shares
964 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
965 // skip encrypted pre-shares we're not interested in
966 pos += sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * idx;
967 return (struct GNUNET_CRYPTO_PaillierCiphertext *) pos;
968}
969
970
902static void 971static void
903keygen_round2_new_element (void *cls, 972keygen_round2_new_element (void *cls,
904 const struct GNUNET_SET_Element *element) 973 const struct GNUNET_SET_Element *element)
@@ -906,8 +975,11 @@ keygen_round2_new_element (void *cls,
906 struct KeygenSession *ks = cls; 975 struct KeygenSession *ks = cls;
907 const struct GNUNET_SECRETSHARING_KeygenRevealData *d; 976 const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
908 struct KeygenPeerInfo *info; 977 struct KeygenPeerInfo *info;
909 unsigned char *pos;
910 size_t expected_element_size; 978 size_t expected_element_size;
979 unsigned int j;
980 gcry_mpi_t tmp;
981 gcry_mpi_t public_key_share;
982 gcry_mpi_t preshare;
911 983
912 if (NULL == element) 984 if (NULL == element)
913 { 985 {
@@ -958,26 +1030,6 @@ keygen_round2_new_element (void *cls,
958 1030
959 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n"); 1031 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
960 1032
961 pos = (void *) &d[1];
962 // skip exponentiated pre-shares
963 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
964 // skip encrypted pre-shares
965 pos += sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * ks->num_peers;
966 // the first exponentiated coefficient is the public key share
967 GNUNET_CRYPTO_mpi_scan_unsigned (&info->public_key_share, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
968
969 pos = (void *) &d[1];
970 // skip exp. pre-shares
971 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
972 // skip to the encrypted value for our peer
973 pos += sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * ks->local_peer_idx;
974
975 GNUNET_assert (NULL != (info->decrypted_preshare = gcry_mpi_new (0)));
976 GNUNET_CRYPTO_paillier_decrypt (&ks->paillier_private_key, &ks->info[ks->local_peer_idx].paillier_public_key,
977 (struct GNUNET_CRYPTO_PaillierCiphertext *) pos, info->decrypted_preshare);
978
979 // TODO: validate zero knowledge proofs
980
981 if (ntohl (d->purpose.size) != 1033 if (ntohl (d->purpose.size) !=
982 element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose)) 1034 element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose))
983 { 1035 {
@@ -991,6 +1043,84 @@ keygen_round2_new_element (void *cls,
991 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n"); 1043 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n");
992 return; 1044 return;
993 } 1045 }
1046
1047 public_key_share = keygen_reveal_get_exp_coeff (ks, d, 0);
1048 info->preshare_commitment = keygen_reveal_get_exp_preshare (ks, d, ks->local_peer_idx);
1049
1050 if (NULL == ks->public_key)
1051 {
1052 GNUNET_assert (NULL != (ks->public_key = gcry_mpi_new (0)));
1053 gcry_mpi_set_ui (ks->public_key, 1);
1054 }
1055 gcry_mpi_mulm (ks->public_key, ks->public_key, public_key_share, elgamal_p);
1056
1057 GNUNET_assert (NULL != (preshare = gcry_mpi_new (0)));
1058 GNUNET_CRYPTO_paillier_decrypt (&ks->paillier_private_key,
1059 &ks->info[ks->local_peer_idx].paillier_public_key,
1060 keygen_reveal_get_enc_preshare (ks, d, ks->local_peer_idx),
1061 preshare);
1062
1063 GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
1064 gcry_mpi_powm (tmp, elgamal_g, preshare, elgamal_p);
1065
1066 // TODO: restore a valid secret from the decryption (the hard part, solving SVP with gauss)
1067 if (0 != gcry_mpi_cmp (tmp, info->preshare_commitment))
1068 {
1069 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Got invalid presecret from P%u\n",
1070 (unsigned int) ks->local_peer_idx, (unsigned int) (info - ks->info));
1071 return;
1072 }
1073
1074 if (NULL == ks->my_share)
1075 {
1076 GNUNET_assert (NULL != (ks->my_share = gcry_mpi_new (0)));
1077 }
1078 gcry_mpi_addm (ks->my_share, ks->my_share, preshare, elgamal_q);
1079
1080 for (j = 0; j < ks->num_peers; j++)
1081 {
1082 gcry_mpi_t presigma;
1083 if (NULL == ks->info[j].sigma)
1084 {
1085 GNUNET_assert (NULL != (ks->info[j].sigma = gcry_mpi_new (0)));
1086 gcry_mpi_set_ui (ks->info[j].sigma, 1);
1087 }
1088 presigma = keygen_reveal_get_exp_preshare (ks, d, j);
1089 gcry_mpi_mulm (ks->info[j].sigma, ks->info[j].sigma, presigma, elgamal_p);
1090 }
1091
1092 gcry_mpi_t prod;
1093 GNUNET_assert (NULL != (prod = gcry_mpi_new (0)));
1094 gcry_mpi_t j_to_k;
1095 GNUNET_assert (NULL != (j_to_k = gcry_mpi_new (0)));
1096 // validate that the polynomial sharing matches the additive sharing
1097 for (j = 0; j < ks->num_peers; j++)
1098 {
1099 unsigned int k;
1100 gcry_mpi_t tmp;
1101 gcry_mpi_t exp_preshare;
1102 gcry_mpi_set_ui (prod, 1);
1103 for (k = 0; k < ks->threshold; k++)
1104 {
1105 // Using pow(double,double) is a bit sketchy.
1106 // We count players from 1, but shares from 0.
1107 gcry_mpi_set_ui (j_to_k, (unsigned int) pow(j+1, k));
1108 tmp = keygen_reveal_get_exp_coeff (ks, d, k);
1109 gcry_mpi_powm (tmp, tmp, j_to_k, elgamal_p);
1110 gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1111 }
1112 exp_preshare = keygen_reveal_get_exp_preshare (ks, d, j);
1113 gcry_mpi_mod (exp_preshare, exp_preshare, elgamal_p);
1114 if (0 != gcry_mpi_cmp (prod, exp_preshare))
1115 {
1116 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: reveal data from P%u incorrect\n",
1117 ks->local_peer_idx, j);
1118 /* no need for further verification, round2 stays invalid ... */
1119 return;
1120 }
1121 }
1122
1123 // TODO: verify proof of fair encryption (once implemented)
994 1124
995 info->round2_valid = GNUNET_YES; 1125 info->round2_valid = GNUNET_YES;
996} 1126}
@@ -1205,6 +1335,23 @@ decrypt_conclude (void *cls)
1205 1335
1206 1336
1207/** 1337/**
1338 * Get a string representation of an MPI.
1339 * The caller must free the returned string.
1340 *
1341 * @param mpi mpi to convert to a string
1342 * @return string representation of @a mpi, must be free'd by the caller
1343 */
1344static char *
1345mpi_to_str (gcry_mpi_t mpi)
1346{
1347 unsigned char *buf;
1348
1349 GNUNET_assert (0 == gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, mpi));
1350 return (char *) buf;
1351}
1352
1353
1354/**
1208 * Called when a new partial decryption arrives. 1355 * Called when a new partial decryption arrives.
1209 */ 1356 */
1210static void 1357static void
@@ -1214,6 +1361,27 @@ decrypt_new_element (void *cls,
1214 struct DecryptSession *session = cls; 1361 struct DecryptSession *session = cls;
1215 const struct GNUNET_SECRETSHARING_DecryptData *d; 1362 const struct GNUNET_SECRETSHARING_DecryptData *d;
1216 struct DecryptPeerInfo *info; 1363 struct DecryptPeerInfo *info;
1364 struct GNUNET_HashCode challenge_hash;
1365
1366 /* nizk response */
1367 gcry_mpi_t r;
1368 /* nizk challenge */
1369 gcry_mpi_t challenge;
1370 /* nizk commit1, g^\beta */
1371 gcry_mpi_t commit1;
1372 /* nizk commit2, c_1^\beta */
1373 gcry_mpi_t commit2;
1374 /* homomorphic commitment to the peer's share,
1375 * public key share */
1376 gcry_mpi_t sigma;
1377 /* partial decryption we received */
1378 gcry_mpi_t w;
1379 /* ciphertext component #1 */
1380 gcry_mpi_t c1;
1381 /* temporary variable (for comparision) #1 */
1382 gcry_mpi_t tmp1;
1383 /* temporary variable (for comparision) #2 */
1384 gcry_mpi_t tmp2;
1217 1385
1218 if (NULL == element) 1386 if (NULL == element)
1219 { 1387 {
@@ -1246,19 +1414,101 @@ decrypt_new_element (void *cls,
1246 return; 1414 return;
1247 } 1415 }
1248 1416
1249 // FIXME: check NIZP first 1417 if (0 != memcmp (&d->ciphertext, &session->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext)))
1418 {
1419 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: got decrypt element with non-matching ciphertext from P%u\n",
1420 (unsigned int) session->share->my_peer, (unsigned int) (info - session->info));
1421
1422 return;
1423 }
1424
1425
1426 GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) d,
1427 offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) -
1428 offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext),
1429 &challenge_hash);
1430
1431 GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
1432 sizeof (struct GNUNET_HashCode));
1433
1434 GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &session->share->sigmas[info - session->info],
1435 sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1436
1437 GNUNET_CRYPTO_mpi_scan_unsigned (&c1, session->ciphertext.c1_bits,
1438 sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1439
1440 GNUNET_CRYPTO_mpi_scan_unsigned (&commit1, &d->nizk_commit1,
1441 sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1442
1443 GNUNET_CRYPTO_mpi_scan_unsigned (&commit2, &d->nizk_commit2,
1444 sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1445
1446 GNUNET_CRYPTO_mpi_scan_unsigned (&r, &d->nizk_response,
1447 sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1448
1449 GNUNET_CRYPTO_mpi_scan_unsigned (&w, &d->partial_decryption,
1450 sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1451
1452 GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0)));
1453 GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0)));
1454
1455 // tmp1 = g^r
1456 gcry_mpi_powm (tmp1, elgamal_g, r, elgamal_p);
1457
1458 // tmp2 = g^\beta * \sigma^challenge
1459 gcry_mpi_powm (tmp2, sigma, challenge, elgamal_p);
1460 gcry_mpi_mulm (tmp2, tmp2, commit1, elgamal_p);
1461
1462 if (0 != gcry_mpi_cmp (tmp1, tmp2))
1463 {
1464 char *tmp1_str;
1465 char *tmp2_str;
1466 tmp1_str = mpi_to_str (tmp1);
1467 tmp2_str = mpi_to_str (tmp2);
1468 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Received invalid partial decryption from P%u (eqn 1), expected %s got %s\n",
1469 session->share->my_peer, info - session->info, tmp1_str, tmp2_str);
1470 GNUNET_free (tmp1_str);
1471 GNUNET_free (tmp2_str);
1472 // return;
1473 }
1474
1475
1476 gcry_mpi_powm (tmp1, c1, r, elgamal_p);
1477
1478 gcry_mpi_powm (tmp2, w, challenge, elgamal_p);
1479 gcry_mpi_mulm (tmp2, tmp2, commit2, elgamal_p);
1480
1481
1482 if (0 != gcry_mpi_cmp (tmp1, tmp2))
1483 {
1484 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Received invalid partial decryption from P%u (eqn 2)\n",
1485 session->share->my_peer, info - session->info);
1486 // return;
1487 }
1488
1250 1489
1251 GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption, 1490 GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption,
1252 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); 1491 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1253} 1492}
1254 1493
1494
1255static void 1495static void
1256insert_decrypt_element (struct DecryptSession *ds) 1496insert_decrypt_element (struct DecryptSession *ds)
1257{ 1497{
1258 struct GNUNET_SECRETSHARING_DecryptData d; 1498 struct GNUNET_SECRETSHARING_DecryptData d;
1259 struct GNUNET_SET_Element element; 1499 struct GNUNET_SET_Element element;
1260 gcry_mpi_t x; 1500 /* our share */
1261 gcry_mpi_t s; 1501 gcry_mpi_t s;
1502 /* partial decryption with our share */
1503 gcry_mpi_t w;
1504 /* first component of the elgamal ciphertext */
1505 gcry_mpi_t c1;
1506 /* nonce for dlog zkp */
1507 gcry_mpi_t beta;
1508 gcry_mpi_t tmp;
1509 gcry_mpi_t challenge;
1510 gcry_mpi_t sigma;
1511 struct GNUNET_HashCode challenge_hash;
1262 1512
1263 /* make vagrind happy until we implement the real deal ... */ 1513 /* make vagrind happy until we implement the real deal ... */
1264 memset (&d, 0, sizeof d); 1514 memset (&d, 0, sizeof d);
@@ -1266,12 +1516,36 @@ insert_decrypt_element (struct DecryptSession *ds)
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n", 1516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n",
1267 ds->share->my_peer); 1517 ds->share->my_peer);
1268 1518
1269 GNUNET_CRYPTO_mpi_scan_unsigned (&x, &ds->ciphertext.c1_bits, 1519 GNUNET_assert (ds->share->my_peer < ds->share->num_peers);
1520
1521 GNUNET_CRYPTO_mpi_scan_unsigned (&c1, &ds->ciphertext.c1_bits,
1270 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); 1522 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1271 GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share, 1523 GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share,
1272 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); 1524 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1525 GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &ds->share->sigmas[ds->share->my_peer],
1526 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1273 1527
1274 gcry_mpi_powm (x, x, s, elgamal_p); 1528 GNUNET_assert (NULL != (w = gcry_mpi_new (0)));
1529 GNUNET_assert (NULL != (beta = gcry_mpi_new (0)));
1530 GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
1531
1532 // FIXME: unnecessary, remove once crypto works
1533 gcry_mpi_powm (tmp, elgamal_g, s, elgamal_p);
1534 if (0 != gcry_mpi_cmp (tmp, sigma))
1535 {
1536 char *sigma_str = mpi_to_str (sigma);
1537 char *tmp_str = mpi_to_str (tmp);
1538 char *s_str = mpi_to_str (s);
1539 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Share of P%u is invalid, ref sigma %s, "
1540 "computed sigma %s, s %s\n",
1541 ds->share->my_peer,
1542 sigma_str, tmp_str, s_str);
1543 GNUNET_free (sigma_str);
1544 GNUNET_free (tmp_str);
1545 GNUNET_free (s_str);
1546 }
1547
1548 gcry_mpi_powm (w, c1, s, elgamal_p);
1275 1549
1276 element.data = (void *) &d; 1550 element.data = (void *) &d;
1277 element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData); 1551 element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
@@ -1279,13 +1553,42 @@ insert_decrypt_element (struct DecryptSession *ds)
1279 1553
1280 d.ciphertext = ds->ciphertext; 1554 d.ciphertext = ds->ciphertext;
1281 d.peer = my_peer; 1555 d.peer = my_peer;
1556 GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, w);
1557
1558 // create the zero knowledge proof
1559 // randomly choose beta such that 0 < beta < q
1560 do
1561 {
1562 gcry_mpi_randomize (beta, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
1563 } while ((gcry_mpi_cmp_ui (beta, 0) == 0) || (gcry_mpi_cmp (beta, elgamal_q) >= 0));
1564 // tmp = g^beta
1565 gcry_mpi_powm (tmp, elgamal_g, beta, elgamal_p);
1566 GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit1, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp);
1567 // tmp = (c_1)^beta
1568 gcry_mpi_powm (tmp, c1, beta, elgamal_p);
1569 GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit2, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp);
1570
1571 // the challenge is the hash of everything up to the response
1572 GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) &d,
1573 offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) -
1574 offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext),
1575 &challenge_hash);
1576
1577 GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
1578 sizeof (struct GNUNET_HashCode));
1579
1580 // compute the response in tmp,
1581 // tmp = (c * s + beta) mod q
1582 gcry_mpi_mulm (tmp, challenge, s, elgamal_q);
1583 gcry_mpi_addm (tmp, tmp, beta, elgamal_q);
1584
1585 GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_response, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp);
1586
1282 d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose)); 1587 d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose));
1283 d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION); 1588 d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
1284 1589
1285 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature); 1590 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature);
1286 1591
1287 GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, x);
1288
1289 GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL); 1592 GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
1290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element done!\n", 1593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element done!\n",
1291 ds->share->my_peer); 1594 ds->share->my_peer);
diff --git a/src/secretsharing/secretsharing.h b/src/secretsharing/secretsharing.h
index 796feabae..227349b05 100644
--- a/src/secretsharing/secretsharing.h
+++ b/src/secretsharing/secretsharing.h
@@ -198,8 +198,8 @@ struct GNUNET_SECRETSHARING_Share
198 uint16_t my_peer; 198 uint16_t my_peer;
199 199
200 /** 200 /**
201 * Public key. Must correspond to the product of 201 * Public key. Computed from the
202 * the homomorphic share commitments. 202 * exponentiated coefficients.
203 */ 203 */
204 struct GNUNET_SECRETSHARING_PublicKey public_key; 204 struct GNUNET_SECRETSHARING_PublicKey public_key;
205 205
@@ -214,9 +214,10 @@ struct GNUNET_SECRETSHARING_Share
214 struct GNUNET_PeerIdentity *peers; 214 struct GNUNET_PeerIdentity *peers;
215 215
216 /* 216 /*
217 * Homomorphic commitments to each peer's share (includes 'my_peer') 217 * For each peer, store elgamal_g to the peer's
218 * share.
218 */ 219 */
219 struct GNUNET_SECRETSHARING_FieldElement *hom_share_commitments; 220 struct GNUNET_SECRETSHARING_FieldElement *sigmas;
220 221
221 /* 222 /*
222 * Original indices of peers from the DKG round. 223 * Original indices of peers from the DKG round.
diff --git a/src/secretsharing/secretsharing_common.c b/src/secretsharing/secretsharing_common.c
index 9f21a1102..7fe8f4666 100644
--- a/src/secretsharing/secretsharing_common.c
+++ b/src/secretsharing/secretsharing_common.c
@@ -62,8 +62,8 @@ GNUNET_SECRETSHARING_share_read (const void *data, size_t len, size_t *readlen)
62 p += n; 62 p += n;
63 63
64 n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement); 64 n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement);
65 share->hom_share_commitments = GNUNET_malloc (n); 65 share->sigmas= GNUNET_malloc (n);
66 memcpy (share->hom_share_commitments, p, n); 66 memcpy (share->sigmas, p, n);
67 p += n; 67 p += n;
68 68
69 n = share->num_peers * sizeof (uint16_t); 69 n = share->num_peers * sizeof (uint16_t);
@@ -125,7 +125,7 @@ GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share
125 p += n; 125 p += n;
126 126
127 n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement); 127 n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement);
128 memcpy (p, share->hom_share_commitments, n); 128 memcpy (p, share->sigmas, n);
129 p += n; 129 p += n;
130 130
131 n = share->num_peers * sizeof (uint16_t); 131 n = share->num_peers * sizeof (uint16_t);
diff --git a/src/secretsharing/test_secretsharing.conf b/src/secretsharing/test_secretsharing.conf
index 6ce865e3a..44b9adf3d 100644
--- a/src/secretsharing/test_secretsharing.conf
+++ b/src/secretsharing/test_secretsharing.conf
@@ -1,6 +1,7 @@
1[secretsharing] 1[secretsharing]
2AUTOSTART = YES 2AUTOSTART = YES
3#PREFIX = valgrind 3#PREFIX = valgrind
4OPTIONS = -LINFO
4 5
5[consensus] 6[consensus]
6AUTOSTART = YES 7AUTOSTART = YES
@@ -13,6 +14,7 @@ DEFAULTSERVICES = core consensus set secretsharing
13 14
14[set] 15[set]
15OPTIONS = -L INFO 16OPTIONS = -L INFO
17AUTOSTART = YES
16#PREFIX = valgrind --leak-check=full 18#PREFIX = valgrind --leak-check=full
17 19
18[testbed] 20[testbed]