GNUnet 0.22.2
gnsrecord_pow.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
24#include "platform.h"
25#include "gnunet_common.h"
26#include "gnunet_util_lib.h"
28#include "gnunet_signatures.h"
29#include <inttypes.h>
30#include "gnsrecord_crypto.h"
31
36struct BestPow
37{
41 uint64_t pow;
42
46 unsigned int bits;
47};
48
49
55{
60
65
69 uint64_t current_pow;
70
75 unsigned int epochs;
76
80 unsigned int difficulty;
81
82};
83
84static struct GNUNET_CRYPTO_PowSalt salt = { "GnsRevocationPow" };
85
92static unsigned int
94{
95 double sum = 0.0;
96 for (unsigned int j = 0; j<POW_COUNT; j++)
97 sum += ph->best[j].bits;
98 return sum / POW_COUNT;
99}
100
101
104{
106 const struct GNUNET_CRYPTO_PublicKey *pk;
107 size_t ksize;
108
109 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
111 spurp = GNUNET_malloc (sizeof (*spurp) + ksize);
112 spurp->timestamp = pow->timestamp;
114 spurp->purpose.size = htonl (sizeof(*spurp) + ksize);
116 (char*) &spurp[1],
117 ksize);
118 return spurp;
119}
120
121
124 const struct GNUNET_CRYPTO_PublicKey *key)
125{
127 unsigned char *sig;
128 size_t ksize;
129 int ret;
130
132 spurp = GNR_create_signature_message (pow);
133 sig = ((unsigned char*) &pow[1] + ksize);
134 ret =
137 &spurp->purpose,
138 sig,
139 key);
140 GNUNET_free (spurp);
141 return ret == GNUNET_OK ? GNUNET_OK : GNUNET_SYSERR;
142}
143
144
147{
148 const struct GNUNET_CRYPTO_PublicKey *pk;
149
150 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
151 return check_signature_identity (pow, pk);
152}
153
154
165 unsigned int difficulty,
167{
168 char buf[sizeof(struct GNUNET_CRYPTO_PublicKey)
169 + sizeof (struct GNUNET_TIME_AbsoluteNBO)
170 + sizeof (uint64_t)] GNUNET_ALIGN;
171 struct GNUNET_HashCode result;
172 struct GNUNET_TIME_Absolute ts;
173 struct GNUNET_TIME_Absolute exp;
175 struct GNUNET_TIME_Relative buffer;
176 /* LSD0001: D' */
177 unsigned int score = 0;
178 unsigned int tmp_score = 0;
179 unsigned int epochs;
180 uint64_t pow_val;
181 ssize_t pklen;
182 const struct GNUNET_CRYPTO_PublicKey *pk;
183
184 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
185
189 if (GNUNET_OK != check_signature (pow))
190 {
192 "Proof of work signature invalid!\n");
193 return GNUNET_SYSERR;
194 }
195
199 for (unsigned int i = 0; i < POW_COUNT - 1; i++)
200 {
201 if (GNUNET_ntohll (pow->pow[i]) >= GNUNET_ntohll (pow->pow[i + 1]))
202 return GNUNET_NO;
203 }
204 GNUNET_memcpy (&buf[sizeof(uint64_t)],
205 &pow->timestamp,
206 sizeof (uint64_t));
208 if (0 > pklen)
209 {
210 GNUNET_break (0);
211 return GNUNET_NO;
212 }
213 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
214 pk,
215 pklen);
216 for (unsigned int i = 0; i < POW_COUNT; i++)
217 {
218 pow_val = GNUNET_ntohll (pow->pow[i]);
219 GNUNET_memcpy (buf, &pow->pow[i], sizeof(uint64_t));
221 buf,
222 sizeof(buf),
223 &result);
226 "Score %u with %" PRIu64 " (#%u)\n",
227 tmp_score, pow_val, i);
228
229 score += tmp_score;
230
231 }
232 score = score / POW_COUNT;
233 if (score < difficulty)
234 return GNUNET_NO;
235 /* LSD0001: (D'-D+1) */
236 epochs = score - difficulty + 1;
237
243 epochs);
248 10);
249 exp = GNUNET_TIME_absolute_add (ts, ttl);
250 exp = GNUNET_TIME_absolute_add (exp,
251 buffer);
252
253 if (0 != GNUNET_TIME_absolute_get_remaining (ts).rel_value_us)
254 return GNUNET_NO; /* Not yet valid. */
255 /* Revert to actual start time */
257 buffer);
258
259 if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
260 return GNUNET_NO; /* expired */
261 return GNUNET_YES;
262}
263
264
267 struct GNUNET_GNSRECORD_PowP *pow)
268{
271 const struct GNUNET_CRYPTO_PublicKey *pk;
272 size_t ksize;
273 char *sig;
275
282 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
286 sig = ((char*) &pow[1]) + ksize;
288 &rp->purpose,
289 (void*) sig);
290 GNUNET_free (rp);
291 if (result == GNUNET_SYSERR)
292 return GNUNET_NO;
293 else
294 return result;
295}
296
297
300 struct GNUNET_GNSRECORD_PowP *pow)
301{
303
304 pk = (struct GNUNET_CRYPTO_PublicKey *) &pow[1];
306 return sign_pow_identity (key, pow);
307}
308
309
316void
318 struct GNUNET_GNSRECORD_PowP *pow)
319{
321}
322
323
326 int epochs,
327 unsigned int difficulty)
328{
331
332
334 pc->pow = pow;
336 epochs);
337 pc->pow->ttl = GNUNET_TIME_relative_hton (ttl);
339 UINT64_MAX);
340 pc->difficulty = difficulty;
341 pc->epochs = epochs;
342 return pc;
343}
344
345
353static int
354cmp_pow_value (const void *a, const void *b)
355{
356 return (GNUNET_ntohll (*(uint64_t*) a) - GNUNET_ntohll (*(uint64_t*) b));
357}
358
359
372{
373 char buf[sizeof(struct GNUNET_CRYPTO_PublicKey)
374 + sizeof (uint64_t)
375 + sizeof (uint64_t)] GNUNET_ALIGN;
376 struct GNUNET_HashCode result;
377 const struct GNUNET_CRYPTO_PublicKey *pk;
378 unsigned int zeros;
379 int ret;
380 uint64_t pow_nbo;
381 ssize_t ksize;
382
383 pc->current_pow++;
384 pk = (const struct GNUNET_CRYPTO_PublicKey *) &(pc->pow[1]);
385
389 for (unsigned int i = 0; i < POW_COUNT; i++)
390 if (pc->current_pow == pc->best[i].pow)
391 return GNUNET_NO;
392 pow_nbo = GNUNET_htonll (pc->current_pow);
393 GNUNET_memcpy (buf, &pow_nbo, sizeof(uint64_t));
394 GNUNET_memcpy (&buf[sizeof(uint64_t)],
395 &pc->pow->timestamp,
396 sizeof (uint64_t));
398 GNUNET_assert (0 < ksize);
399 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
400 pk,
401 ksize);
403 buf,
404 sizeof(buf),
405 &result);
407 for (unsigned int i = 0; i < POW_COUNT; i++)
408 {
409 if (pc->best[i].bits < zeros)
410 {
411 pc->best[i].bits = zeros;
412 pc->best[i].pow = pc->current_pow;
413 pc->pow->pow[i] = pow_nbo;
415 "New best score %u with %" PRIu64 " (#%u)\n",
416 zeros, pc->current_pow, i);
417
418 break;
419 }
420 }
421 ret = calculate_score (pc) >= pc->difficulty + pc->epochs ? GNUNET_YES :
422 GNUNET_NO;
423 if (GNUNET_YES == ret)
424 {
425 /* Sort POWs) */
426 qsort (pc->pow->pow, POW_COUNT, sizeof (uint64_t), &cmp_pow_value);
427 }
428 return ret;
429}
430
431
432size_t
434{
435 size_t size;
436 size_t ksize;
437 const struct GNUNET_CRYPTO_PublicKey *pk;
438
439 size = sizeof (struct GNUNET_GNSRECORD_PowP);
440 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
442 size += ksize;
444 return size;
445}
446
447
455void
457{
458 GNUNET_free (pc);
459}
API for GNS record-related crypto.
static unsigned int calculate_score(const struct GNUNET_GNSRECORD_PowCalculationHandle *ph)
Calculate the average zeros in the pows.
Definition: gnsrecord_pow.c:93
static enum GNUNET_GenericReturnValue sign_pow_identity(const struct GNUNET_CRYPTO_PrivateKey *key, struct GNUNET_GNSRECORD_PowP *pow)
static enum GNUNET_GenericReturnValue check_signature(const struct GNUNET_GNSRECORD_PowP *pow)
struct GNUNET_GNSRECORD_SignaturePurposePS * GNR_create_signature_message(const struct GNUNET_GNSRECORD_PowP *pow)
Create the revocation metadata to sign for a revocation message.
static int cmp_pow_value(const void *a, const void *b)
Comparison function for quicksort.
static struct GNUNET_CRYPTO_PowSalt salt
Definition: gnsrecord_pow.c:84
static enum GNUNET_GenericReturnValue sign_pow(const struct GNUNET_CRYPTO_PrivateKey *key, struct GNUNET_GNSRECORD_PowP *pow)
static enum GNUNET_GenericReturnValue check_signature_identity(const struct GNUNET_GNSRECORD_PowP *pow, const struct GNUNET_CRYPTO_PublicKey *key)
static int ret
Final status code.
Definition: gnunet-arm.c:93
struct GNUNET_HashCode key
The key used in the DHT.
struct GNUNET_CRYPTO_PrivateKey pk
Private key from command line option, or NULL.
static struct GNUNET_TIME_Relative ttl
Current record $TTL to use.
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
static char * rp
Relying party.
static int result
Global testing status.
static struct GNUNET_TIME_Relative epoch_duration
Epoch length.
static unsigned int epochs
-e option.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
API that can be used to manipulate GNS record data.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
size_t GNUNET_GNSRECORD_proof_get_size(const struct GNUNET_GNSRECORD_PowP *pow)
#define POW_COUNT
The proof-of-work narrowing factor.
void GNUNET_GNSRECORD_pow_stop(struct GNUNET_GNSRECORD_PowCalculationHandle *pc)
Stop a PoW calculation.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_pow_round(struct GNUNET_GNSRECORD_PowCalculationHandle *pc)
Calculate a key revocation valid for broadcasting for a number of epochs.
void GNUNET_GNSRECORD_pow_init(const struct GNUNET_CRYPTO_PrivateKey *key, struct GNUNET_GNSRECORD_PowP *pow)
Initializes a fresh PoW computation.
struct GNUNET_GNSRECORD_PowCalculationHandle * GNUNET_GNSRECORD_pow_start(struct GNUNET_GNSRECORD_PowP *pow, int epochs, unsigned int difficulty)
Starts a proof-of-work calculation given the pow object as well as target epochs and difficulty.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_check_pow(const struct GNUNET_GNSRECORD_PowP *pow, unsigned int difficulty, struct GNUNET_TIME_Relative epoch_duration)
Check if the given proof-of-work is valid.
unsigned int GNUNET_CRYPTO_hash_count_leading_zeros(const struct GNUNET_HashCode *h)
Count the number of leading 0 bits in h.
Definition: crypto_hash.c:174
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_sign_raw_(const struct GNUNET_CRYPTO_PrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, unsigned char *sig)
Sign a given block.
Definition: crypto_pkey.c:266
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_signature_verify_raw_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const unsigned char *sig, const struct GNUNET_CRYPTO_PublicKey *pub)
Verify a given signature.
Definition: crypto_pkey.c:348
ssize_t GNUNET_CRYPTO_public_key_get_length(const struct GNUNET_CRYPTO_PublicKey *key)
Get the compacted length of a GNUNET_CRYPTO_PublicKey.
Definition: crypto_pkey.c:85
#define GNUNET_log(kind,...)
ssize_t GNUNET_CRYPTO_write_public_key_to_buffer(const struct GNUNET_CRYPTO_PublicKey *key, void *buffer, size_t len)
Writes a GNUNET_CRYPTO_PublicKey to a compact buffer.
Definition: crypto_pkey.c:128
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_key_get_public(const struct GNUNET_CRYPTO_PrivateKey *privkey, struct GNUNET_CRYPTO_PublicKey *key)
Retrieves the public key representation of a private key.
Definition: crypto_pkey.c:430
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
ssize_t GNUNET_CRYPTO_signature_get_raw_length_by_type(uint32_t type)
Get the compacted length of a signature by type.
Definition: crypto_pkey.c:209
void GNUNET_CRYPTO_pow_hash(const struct GNUNET_CRYPTO_PowSalt *salt, const void *buf, size_t buf_len, struct GNUNET_HashCode *result)
Calculate the 'proof-of-work' hash (an expensive hash).
Definition: crypto_pow.c:42
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:741
#define GNUNET_TIME_UNIT_WEEKS
One week.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition: time.c:471
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:486
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition: time.c:620
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:452
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:552
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:640
#define GNUNET_TIME_UNIT_YEARS
One year (365 days).
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define GNUNET_SIGNATURE_PURPOSE_GNS_REVOCATION
GNS zone key revocation (GNS)
API for proof of work.
Definition: gnsrecord_pow.c:37
unsigned int bits
Corresponding zero bits in hash.
Definition: gnsrecord_pow.c:46
uint64_t pow
PoW nonce.
Definition: gnsrecord_pow.c:41
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Value for a salt for GNUNET_CRYPTO_pow_hash().
A private key for an identity as per LSD0001.
uint32_t type
Type of public key.
An identity key as per LSD0001.
The handle to a PoW calculation.
Definition: gnsrecord_pow.c:55
unsigned int difficulty
The difficulty (leading zeros) to achieve.
Definition: gnsrecord_pow.c:80
unsigned int epochs
Epochs how long the PoW should be valid.
Definition: gnsrecord_pow.c:75
struct BestPow best[POW_COUNT]
Current set of found PoWs.
Definition: gnsrecord_pow.c:59
struct GNUNET_GNSRECORD_PowP * pow
The final PoW result data structure.
Definition: gnsrecord_pow.c:64
uint64_t current_pow
The current nonce to try.
Definition: gnsrecord_pow.c:69
Struct for a proof of work as part of the revocation.
struct GNUNET_TIME_AbsoluteNBO timestamp
The timestamp of the revocation.
uint64_t pow[32]
The PoWs.
The signature object we use for the PoW.
struct GNUNET_TIME_AbsoluteNBO timestamp
The timestamp of the revocation.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
The signature purpose.
A 512-bit hashcode.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.