ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Digest-Hashcash/Hashcash.pm
Revision: 1.6
Committed: Tue Jul 21 05:01:01 2015 UTC (8 years, 9 months ago) by root
Branch: MAIN
CVS Tags: rel-1_0
Changes since 1.5: +7 -1 lines
Log Message:
1.0

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     Digest::Hashcash - generate Hashcashes (http://www.hashcash.org)
4    
5     =head1 SYNOPSIS
6    
7     use Digest::Hashcash;
8    
9     =head1 DESCRIPTION
10    
11     This module implements the hashcash hash (or digest, although it's
12     not clearly a digest). For all your information needs please visit
13     http://www.hashcash.org.
14    
15     One thing to note about this module is that it requires ISO C99 support,
16     both in your compiler and your standard library. If you don't have a
17     compiler that supports ISO C, get gcc at http://gcc.gnu.org/ :)
18    
19     =over 4
20    
21     =cut
22    
23     package Digest::Hashcash;
24    
25     use Time::Local;
26 root 1.2 use Time::HiRes;
27 root 1.1
28     require XSLoader;
29    
30     no warnings;
31    
32 root 1.6 $VERSION = '1.0';
33 root 1.1
34     XSLoader::load Digest::Hashcash, $VERSION;
35    
36 root 1.2 =item $secs = estimate_time $size
37    
38     Estimate the average time necessary to calculate a token of the given
39     size.
40    
41     See also C<estimate_size>.
42    
43     =item $size = estimate_size $time[, $min]
44    
45     Estimate the size that can be calculated in the given time (which is an
46     upper bound). The function will not return a size less then C<min>.
47    
48     Estimating the time to be used can go wrong by as much as 50% (but is
49     usually quite accurate), and the estimation itself can take as much as a
50     second on slower (<pentium) machines, but faster machines (1Ghz P3 for
51     example) usually handle it within a hundredth of a second or so.
52    
53     The estimation will be done only once, so you can call this fucntion as
54     often as you like without incuring the overhead everytime.
55    
56     =cut
57    
58     my $rounds;
59    
60     sub _rounds {
61     $rounds ||= &_estimate_rounds();
62     }
63    
64     sub estimate_time {
65     my ($size) = @_;
66     2**$size / &_rounds;
67     }
68    
69     sub estimate_size {
70     my ($time, $min) = @_;
71     $time = (log $time * $rounds) / log 2;
72     $time < $min ? $min : int $time;
73     }
74    
75 root 1.4 =item $cipher = new Digest::Hashcash [param => value...]
76 root 1.1
77     =over 4
78    
79 root 1.2 =item size => 18
80 root 1.1
81     The number of collisions, in bits. Every bit increases the time to create
82     the token (and thus the cash) by two.
83    
84     =item uid => ""
85    
86     A string used to make the token more unique (e.g. the senders address)
87     and reduce token collisions. The string must only contain characters
88     valid for the trial part of the token, e.g. uuencoded, base64 or
89     e-mail-address-parts are useful here.
90    
91     =item extrarand => 0
92    
93     The extra bytes of randomness to add to the token in addition to the
94     standard amount. Each byte adds a little bit over 6 bit of randomness to
95     the token.
96    
97     The standard amount of randomness is 8 (> 51 bits of randomness).
98    
99     =item timestamp => 0
100    
101     The timestamp to use. A value of 0 (the default) means to use the current
102     time.
103    
104     =back
105    
106 root 1.4 =item $token = $cipher->hash ($data [, param => value...])
107 root 1.1
108     Creates and returns a new token. This can take some time.
109    
110     Any additional parameters are interpreted the same way as arguments to
111     C<new>.
112    
113 root 1.4 =item $prefix = $cipher->verify ($token [, param => value...]))
114 root 1.1
115     Checks the given token and returns true if the token has the minimum
116     number of prefix bits, or false otherwise. The value returned is actually
117     the number of collisions, so to find the number of collisions bits specify
118     C<< collisions => 0 >>.
119    
120     Any additional parameters are interpreted the same way as arguments to
121     C<new>.
122    
123 root 1.4 =item $resource = $cipher->resource ($token)
124 root 1.1
125     Returns the resource part, or C<undef>.
126    
127 root 1.4 =item $tstamp = $ciper->timestamp ($token)
128 root 1.1
129     Returns the timestamp part (in the same format as perl's C<time>), or
130     C<undef>.
131    
132     =back
133    
134     =cut
135    
136     sub new {
137     my $class = shift;
138    
139     bless { @_ }, $class;
140     }
141    
142     sub hash {
143     my $self = shift;
144     my %arg = (%$self, resource => @_);
145    
146     &_gentoken(@arg{qw(size timestamp resource uid extrarand)});
147     }
148    
149     sub verify {
150     my ($self, $token) = (shift, shift);
151     my %arg = (%$self, @_);
152    
153     my $prefix = &_prefixlen($token);
154    
155     $prefix < $arg{size}
156     ? undef
157     : $prefix;
158     }
159    
160     sub resource {
161     my ($self, $token) = @_;
162    
163     $token =~ /^\d+:\d*:(.*):/
164     or return undef;
165    
166     return $1;
167     }
168    
169     sub timestamp {
170     my ($self, $token) = @_;
171    
172     $token =~ /^\d+:(\d*):.*:/
173     or return undef;
174    
175     my ($y, $m, $d, $H, $M, $S);
176     local $_ = $1;
177     $y = /\G(\d\d)/gc ? $1 : return undef;
178     $m = /\G(\d\d)/gc ? $1 : 1;
179     $d = /\G(\d\d)/gc ? $1 : 1;
180     $H = /\G(\d\d)/gc ? $1 : 0;
181     $M = /\G(\d\d)/gc ? $1 : 0;
182     $S = /\G(\d\d)/gc ? $1 : 0;
183    
184     return timegm $S, $M, $H, $d, $m - 1, $y;
185     }
186    
187     =head1 SEE ALSO
188    
189     L<http://www.hashcash.org>.
190    
191 root 1.6 =head1 SUPPORT FOR THE PERL MULTICORE SPECIFICATION
192    
193     This module supports the perl multicore specification
194     (<http://perlmulticore.schmorp.de/>) for token generation of any length
195     and size.
196    
197 root 1.1 =head1 BUGS
198    
199     * There is a y2k+100 problem, as I always assume the same as Time::Local.
200     This is a problem with the hashcash specification, which specifies
201 root 1.3 years as 2 digits :(
202 root 1.1
203     =head1 AUTHOR
204    
205 root 1.5 Marc Lehmann <schmorp@schmorp.de>
206 root 1.1 http://home.schmorp.de
207    
208     =cut
209    
210     1;
211