ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Digest-Hashcash/Hashcash.pm
Revision: 1.8
Committed: Wed Jul 22 12:09:48 2015 UTC (8 years, 9 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +20 -17 lines
Log Message:
*** empty log message ***

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