aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_kdf.c
diff options
context:
space:
mode:
authorJeff Burdges <burdges@gnunet.org>2016-05-30 15:54:56 +0000
committerJeff Burdges <burdges@gnunet.org>2016-05-30 15:54:56 +0000
commitafb40a6d7a49d2608b709d6e8863675a6a301c99 (patch)
tree26c97c0217311d2313ecac5daa853d428ecf9025 /src/util/crypto_kdf.c
parent295a7ab56564369098a12e2cc39fac0d5225c465 (diff)
downloadgnunet-afb40a6d7a49d2608b709d6e8863675a6a301c99.tar.gz
gnunet-afb40a6d7a49d2608b709d6e8863675a6a301c99.zip
Use a uniform random number mod an RSA composites for both
the blinding factor and the full domain hash. This resolves an attack against the blinding factor in Taler: There was a call to GNUNET_CRYPTO_kdf in bkey = rsa_blinding_key_derive (len, bks); that gives exactly len bits where len = GNUNET_CRYPTO_rsa_public_key_len (pkey); Now r = 2^(len-1)/pkey.n is the probability that a set high bit being okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey > pkey.n making the effective bkey be bkey mod pkey.n = bkey - pkey.n so the effective bkey has its high bit set with probability r/2. We expect r to be close to 1/2 if the exchange is honest, but the exchange can choose r otherwise. In blind signing, the exchange sees B = bkey * S mod pkey.n On deposit, the exchange sees S so they can compute bkey' = B/S mod pkey.n for all B they recorded to see if bkey' has it's high bit set. Also, note the exchange can compute 1/S efficiently since they know the factors of pkey.n. I suppose that happens with probability r/(1+r) if its the wrong B, not completely sure. If otoh we've the right B, then we've the probability r/2 of a set high bit in the effective bkey. Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving the wrong and right probabilities 1/3 and 1/4, respectively. I fear this gives the exchange a meaningful fraction of a bit of information per coin involved in the transaction. It sounds damaging if numerous coins were involved. And it could run across transactions in some scenarios. I suspect we need a more uniform deterministic pseudo-random number generator for blinding factors. Just fyi, our old call to gcry_mpi_randomize had this same problem. I do not believe this caused a problem for the full domain hash, but we can fix it easily enough anyways.
Diffstat (limited to 'src/util/crypto_kdf.c')
-rw-r--r--src/util/crypto_kdf.c68
1 files changed, 64 insertions, 4 deletions
diff --git a/src/util/crypto_kdf.c b/src/util/crypto_kdf.c
index 242fbf296..056fda529 100644
--- a/src/util/crypto_kdf.c
+++ b/src/util/crypto_kdf.c
@@ -22,6 +22,7 @@
22 * @file src/util/crypto_kdf.c 22 * @file src/util/crypto_kdf.c
23 * @brief Key derivation 23 * @brief Key derivation
24 * @author Nils Durner 24 * @author Nils Durner
25 * @author Jeffrey Burdges <burdges@gnunet.org>
25 */ 26 */
26 27
27#include <gcrypt.h> 28#include <gcrypt.h>
@@ -43,8 +44,9 @@
43 * @return #GNUNET_YES on success 44 * @return #GNUNET_YES on success
44 */ 45 */
45int 46int
46GNUNET_CRYPTO_kdf_v (void *result, size_t out_len, const void *xts, 47GNUNET_CRYPTO_kdf_v (void *result, size_t out_len,
47 size_t xts_len, const void *skm, size_t skm_len, 48 const void *xts, size_t xts_len,
49 const void *skm, size_t skm_len,
48 va_list argp) 50 va_list argp)
49{ 51{
50 /* 52 /*
@@ -76,8 +78,9 @@ GNUNET_CRYPTO_kdf_v (void *result, size_t out_len, const void *xts,
76 * @return #GNUNET_YES on success 78 * @return #GNUNET_YES on success
77 */ 79 */
78int 80int
79GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts, 81GNUNET_CRYPTO_kdf (void *result, size_t out_len,
80 size_t xts_len, const void *skm, size_t skm_len, ...) 82 const void *xts, size_t xts_len,
83 const void *skm, size_t skm_len, ...)
81{ 84{
82 va_list argp; 85 va_list argp;
83 int ret; 86 int ret;
@@ -88,3 +91,60 @@ GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts,
88 91
89 return ret; 92 return ret;
90} 93}
94
95
96/**
97 * Deterministically generate a pseudo-random number uniformly from the
98 * integers modulo a libgcrypt mpi.
99 *
100 * @param[out] r MPI value set to the FDH
101 * @param n MPI to work modulo
102 * @param xts salt
103 * @param xts_len length of @a xts
104 * @param skm source key material
105 * @param skm_len length of @a skm
106 * @param ctx context string
107 */
108void
109GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
110 gcry_mpi_t n,
111 const void *xts, size_t xts_len,
112 const void *skm, size_t skm_len,
113 const char *ctx)
114{
115 gcry_error_t rc;
116 unsigned int nbits;
117 size_t rsize;
118 unsigned int ctr;
119
120 nbits = gcry_mpi_get_nbits (n);
121 /* GNUNET_assert (nbits > 512); */
122
123 ctr = 0;
124 do {
125 /* Ain't clear if n is always divisible by 8 */
126 uint8_t buf[ (nbits-1)/8 + 1 ];
127
128 rc = GNUNET_CRYPTO_kdf (buf,
129 sizeof (buf),
130 xts, xts_len,
131 skm, skm_len,
132 ctx, strlen(ctx),
133 &ctr, sizeof(ctr),
134 NULL, 0);
135 GNUNET_assert (GNUNET_YES == rc);
136
137 rc = gcry_mpi_scan (r,
138 GCRYMPI_FMT_USG,
139 (const unsigned char *) buf,
140 sizeof (buf),
141 &rsize);
142 GNUNET_assert (0 == rc); /* Allocation erro? */
143
144 gcry_mpi_clear_highbit (*r, nbits);
145 GNUNET_assert( 0 == gcry_mpi_test_bit (*r, nbits) );
146 ++ctr;
147 } while ( 0 <= gcry_mpi_cmp(*r,n) );
148}
149
150