1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
#include "crypt.h"
#include "sha1.h"
#include "hashcash.h"
#include "serial.h"
/*
*
* Copyright (C) 1999 Frans Kaashoek and David Mazieres (kaashoek@lcs.mit.edu)
*
* This program 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 2, or (at
* your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*/
/* This is a simple implementation of hashcash for SFS. It is inspired by
* http://www.cypherspace.org/~adam/hashcash/
*/
static void
addone (u_char *p, u_int len)
{
for (int i = len - 1; i >= 0; i--) {
p[i]++;
if (p[i] != 0)
break;
}
}
static bool
check (const u_int32_t *l, const u_int32_t *r, unsigned int n)
{
int nword = n / (sizeof(u_int32_t) * 8);
int nbits = n % (sizeof(u_int32_t) * 8);
int i;
for (i = 0; i < nword; i++)
if (l[i] != r[i])
return false;
if (nbits > 0) {
u_int32_t mask = ~((1 << (sizeof(u_int32_t) * 8 - nbits)) - 1);
return (l[i] & mask) == (r[i] & mask);
}
else
return true;
}
/* Compute a payment such that the first "bitcost" bits of
* SHA1-transfer(payment) match the first "bitcost" bits of the target. The
* SHA1-state is initialized to the value of inithash (e.g the hostid). */
u_long
hashcash_pay (char payment[sha1::blocksize],
const char inithash[sha1::hashsize],
const char target[sha1::hashsize], unsigned int bitcost)
{
u_int32_t state[sha1::hashwords];
u_int32_t s[sha1::hashwords];
u_int32_t t[sha1::hashwords];
u_char *pay = reinterpret_cast<u_char *> (payment);
rnd.getbytes (pay, sha1::blocksize);
for (int i = 0; i < sha1::hashwords; i++) {
s[i] = getint (inithash + 4 * i);
t[i] = getint (target + 4 * i);
}
for (unsigned long j = 0; 1; j++) {
for (int i = 0; i < sha1::hashwords; i++)
state[i] = s[i];
sha1::transform (state, pay);
if (check (state, t, bitcost))
return j;
else
addone (pay, sha1::blocksize);
}
}
bool
hashcash_check (const char payment[sha1::blocksize],
const char inithash[sha1::hashsize],
const char target[sha1::hashsize], unsigned int bitcost)
{
u_int32_t s[sha1::hashwords];
u_int32_t t[sha1::hashwords];
const u_char *pay = reinterpret_cast<const u_char *> (payment);
for (int i = 0; i < sha1::hashwords; i++) {
s[i] = getint (inithash + 4 * i);
t[i] = getint (target + 4 * i);
}
sha1::transform (s, pay);
return check (s, t, bitcost);
}
|