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

# Content
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 use Time::HiRes;
27
28 no warnings;
29
30 BEGIN {
31 our $VERSION = 1.1;
32
33 require XSLoader;
34 XSLoader::load Digest::Hashcash, $VERSION;
35 }
36
37 =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 The estimation will be done only once, so you can call this function as
55 often as you like without incuring the overhead everytime.
56
57 =cut
58
59 my $rounds;
60
61 sub _rounds() {
62 $rounds ||= _estimate_rounds
63 }
64
65 sub estimate_time($) {
66 my ($size) = @_;
67
68 2**$size / _rounds
69 }
70
71 sub estimate_size($$) {
72 my ($time, $min) = @_;
73
74 $time = (log $time * _rounds) / log 2;
75 $time < $min ? $min : int $time
76 }
77
78 =item $cipher = new Digest::Hashcash [param => value...]
79
80 =over 4
81
82 =item size => 18
83
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 =item $token = $cipher->hash ($data [, param => value...])
110
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 =item $prefix = $cipher->verify ($token [, param => value...]))
117
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 =item $resource = $cipher->resource ($token)
127
128 Returns the resource part, or C<undef>.
129
130 =item $tstamp = $ciper->timestamp ($token)
131
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 &_gentoken (@arg{qw(size timestamp resource uid extrarand)})
150 }
151
152 sub verify {
153 my ($self, $token) = (shift, shift);
154 my %arg = (%$self, @_);
155
156 my $prefix = _prefixlen $token;
157
158 $prefix < $arg{size}
159 ? undef
160 : $prefix
161 }
162
163 sub resource {
164 my ($self, $token) = @_;
165
166 $token =~ /^\d+:\d*:(.*):/
167 or return undef;
168
169 $1
170 }
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 timegm $S, $M, $H, $d, $m - 1, $y
188 }
189
190 =head1 SEE ALSO
191
192 L<http://www.hashcash.org>.
193
194 =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 =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 years as 2 digits :(
205
206 =head1 AUTHOR
207
208 Marc Lehmann <schmorp@schmorp.de>
209 http://home.schmorp.de
210
211 =cut
212
213 1;
214