NAME
hashcash - hashcash anti-spam / denial of service counter-measure tool
SYNOPSIS
Mint (create) token:
hashcash [ *options* ] [ *-b bits* ] [ *resource* ]>
Check token:
hashcash *-c* [ *options* ] *-b bits* *-r resource* [ *token* ]
Speed estimates:
hashcash *-s* [ *options* ] [ *-b bits* ]
Purge database:
hashcash *-p now* [ *-j resource* ] [ *-k* ] [ *-t time* ] [ *-u* ]
Count collision bits:
hashcash *-w* [ *options* ] [ *token* ]
Get resource name:
hashcash *-n* [ *options* ] [ *token* ]
Get time remaining until expiry
hashcash *-l* [ *options* ] *-e period* [ *token* ]
DESCRIPTION
Hashcash is a denial-of-service counter measure tool. It's main current
use is to help hashcash users avoid losing email due to content based
and blacklist based anti-spam systems.
The hashcash tool allows you to create hashcash tokens to attach to
emails you send, and to verify hashcash tokens attached to emails you
receive. Email senders attach hashcash tokens with the X-Hashcash:
header. Vendors and authors of anti-spam tools are encouraged to exempt
mail sent with hashcash from their blacklists and content based
filtering rules.
A hashcash token constitutes a proof-of-work which takes a
parameterizable amount of work to compute for the sender. The recipient
can verify received tokens efficiently. This package also includes a
sha1 implementation which behaves somewhat like md5sum, but with SHA1.
The hashcash proof-of-work function is to compute partial hash
collisions (the SHA1 hash function is used). By choosing the number of
bits of collision, the work required to compute a collision can be made
arbitrarily expensive -- from fractions of a second to minutes or hours.
The verification is efficient requiring the same small cost whatever the
collision size.
For more detailed discussion of other applications hashcash has been
used for see http://www.hashcash.org/
USAGE NOTES
In this man page a resource name is the name of the service or address
the token is created for. In the case of email, the resource name is the
recipient's email address in the form user@domain.com.
Minting tokens
If neither the *-c* or *-s* option are given, it is assumed that you
want to mint a token.
The resource name (recipient's email address) to mint the token against
can be passed as an argument, or if omitted is read from stdin. If stdin
is a tty the user is prompted, if stdin is a pipe the resource name is
just silently read. The desired collision size can be specified with the
-b option. If no collision size is specified, the default is 20 bits. As
a convenience, if stdin is a tty and no collision size is given with the
*-b* flag, the user is prompted for a collision size.
Checking tokens
The *-c* flag must be given to check tokens. The token to check can be
given as an argument to "hashcash". If no token is given the token is
read from stdin. If stdin is a tty the user will be prompted, if stdin
is a pipe the token is just silently read. A resource name (the
recipient's email address) can be given with the *-r* option. If a
resource name is given the resource name is compared to the resource
name in the token, if they do not match, the token is rejected.
Note: if no resource name is given the token is anyway checked to see if
it is otherwise valid, but it could be minted for a different resource,
which would allow tokens to be reused across different resources, so
hashcash will return unchecked exit code on exit.
Tokens are by default considered to be valid forever. The validity
period can be changed using the *-e* flag.
If the token has expired or has a date in the future the token is
rejected and the program exits immediately.
If a required collision size is given with the *-b* flag, the tokens
value is computed and compared, if the token has insufficent value it is
rejected, and the program exits immediately. If the *-b* flag is not
given, the token could be of any size, so hashcash will return unchecked
exit code on exit.
If the token is double spent the token is rejected. Double spending
protection is discussed in more detail below in "Double Spending
Protection". If double spending protection is not enabled, the token
could be double spent, so hashcash will return unchecked exit code (exit
code 2) on exit.
The *-w* flag can be used to request that the number of bits of the
collision are counted and displayed; exit code unchecked (exit code 2)
is returned on exit. The *-n* flag can be used to request that the
resource name in the token is parsed out and displayed; exit code
unchecked (exit code 2) is returned on exit. The *-l* flag can be used
to request the number of seconds until expiry of the token is output;
exit code unchecked (exit code 2) is returned on exit.
The program will only return exit codes valid or invalid if the *-c*
flag is used, and all of the options *-b bits*, *-d*, *-r resource* are
used. These are the minimum set of options necessary to fully check the
validty of a token. If these criteria are not met, the program will
return exit code unchecked (exit code 2) on exit. (See also the *-y*
flag.)
Double Spending Protection
If the *-d* flag is used with the *-c* flag a database of spent tokens
is kept.
By default tokens expire after 28 days, without expiry the database
would grow indefinately. You can specify an alternate expiry period with
the *-e* flag. The recommended (and default) expiry period for email is
28 days. After the expiry period amount of time, the token is anyway
considered expired and may be purged from the database to save space.
(See "Purging Periodically vs on Next Access" for how to purge tokens.)
For efficiency reasons a token is verified before it is checked in the
database; if it is otherwise invalid no database activity will occur.
Note: The decision about how long the token should be considered valid
is up to the verifier. If it is too short it is possible for some
applications that the token will expire before arriving at the recipient
(eg with email.) The suggested value of 28 days should be safe for
normal email delivery delays. The choice is a trade-off between database
size and risk of expiry prior to arrival, and depends on the
application.
Note: Different tokens in the same database can have different validity
periods, so for example tokens for different resources with different
validity periods can be stored in the same database, or the recipient
may change the validity period for future tokens without affecting the
validity of old tokens.
Purging Periodically vs on Next Access
To purge old tokens periodically while checking tokens use the *-p
period* option to purge no sooner than the given time period since the
last purge. Purging can be used with the *-k* option to purge unexpired
tokens also, and with the *-r resource* flag to purge only tokens for
the given resource.
There are circumstances where it may be inconvenient to purge tokens on
the next access, for example if there is a large double spend database
which takes some time to purge, and the response time of the hashcash
checker is important. To avoid this problem, purging can be done
separately using just the *-p now* option to request just the purge
operation. On unix for example you could call "hashcash -p now" in a
cron job once per day, or on demand when disk was running low.
Speed Estimates
The *-s* flag requests measurement of how many collisions can be tested
per second. No token is minted, or verified.
If the *-b* flag is used with this option, instead an estimate of how
many seconds it would take to mint a token of the given size in bits is
computed.
Notes
All informational output is printed on stderr. Minted tokens, and
results of token verification and timing are printed on stdout. The
quiet flag *-q* suppresses all informational output. The *-v* flag
requests more informational output. The requested output, which is the
only information that is output in quiet mode (when *-q* is specified)
is printed on standard output. If stdout is a pipe, or when quiet mode
is in effect the output is printed without description (ie just bits,
just seconds, just resource).
OPTIONS
*-c*
Check the token given as an argument or on stdin for validity.
*-m*
Mint a token. If none of *-c*, *-p*, *-s*, *-l*, *-n*, *-w* are
given it is anyway assumed that the user wishes to mint a token.
*-b bits*
When minting a token, request a collision of this many bits. When
verifying a token require that it have a collision of at minimum
this many bits, otherwise reject it.
*-r resource*
When minting tokens, the resource name (recipient's email address)
to mint the token against can be given either with *-r resource* or
as an argument to "hashcash".
When checking tokens, the resource name (your own email address) can
be given with the *-r* option. If the resource name is given it is
checked against the resource name in the token, and if they do not
match the token is rejected. Note if the resource name is not given,
tokens for other resources would be accepted, and therefore hashcash
returns exit code unchecked (exit code 2) on exit.
*-e time*
Expiry period for spent tokens. While checking tokens (using the
*-c* flag), if the token was minted more than the specified amount
of time ago, it is considered expired. If this option is not used,
by default tokens expire after 28 days. The expiry period is given
in seconds by default (an argument of 0 means forever). A single
character suffix can be used to specify alternate units (m =
minutes, h = hours, d = days, M = months, y = Y = years, and s =
seconds).
If used with the *-d* option, the spent token and it's expiry period
is recorded in the database. See the *-p* option for description of
how to purge tokens from the database.
The following *-e* usage to give an implicit time resolution while
minting is deprecated, use explicit *-z* option instead. (*-z*
overrides *-e* if both are given. *-e* still works for backwards
compatibility. If neither are given the default is 6 chars (time
format: YYMMDD)).
While minting tokens, the *-e* flag can have an effect on the
resolution of time created in the token. Without the *-e* option,
the default resolution is days (time format: YYMMDD). Alternate
formats based on range of expiry period are as follows:
* period >= 2 years then time format YY is used rounded down to the
nearest year start;
* 2 years < period <= 2 months then time format YYMM is used rounded
down to the nearest month start;
* 2 months < period <= 2 days then time format YYMMDD is used
rounded down to the begining of the nearest day;
* 2 days < period <= 2 hours then time format YYMMDDhh is used
rounded down to the begining of the nearest hour;
* 2 hours < period <= 2 minutes then time format YYMMDDhhmm is used
rounded down to the begining of the nearest minute;
* period < 2 minutes then time format YYMMDDhhmmss is used in
seconds.
Note the rounding down is based on UTC time, not local time. This
can lead to initially suprising results when rounding down to eg
days in time zones other than GMT (UTC = GMT). It may be clearer to
understand if you use the *-u* option.
*-z width*
The *-z* option is for use during minting and deprecates the *-e*
option given in combination with *-m* to specify an implicit time
field width. Valid widths are 2,4,6,8,10 or 12 chars corresponding
respectively to: YY, YYMM, YYMMDD, YYMMDDhh, YYMMDDhhmm, and
YYMMDDhhmmss rounded down to the nearest year, month, day, hour,
minute respectively.
Note the rounding down is based on UTC time, not local time. This
can lead to initially suprising results when rounding down to eg
days in time zones other than GMT (UTC = GMT). It may be clearer to
understand if you use the *-u* option.
*-g period*
The *-g* option is for use when checking hashcash stamps with the
*-c* option and specifies a grace period for clock skew, ie if a
hashcash stamp arrives with a date in the future or in the past it
will not be rejected as having a futuristic date (or as being
expired) unless it is more futuristic (or has been expired for
longer) than this period. The default is 2 days, which means as long
as the sending system's clock is no more than 2 days ahead (or 2
days behind) of the receiving system's clock, the hashcash stamp
will still be accepted.
The default units for grace period are seconds. A single character
suffix can be used to specify alternate units (m = minutes, h =
hours, d = days, M = months, y = Y = years, and s = seconds).
*-d*
Store tokens in a double spend database. If token has been seen
before it will be rejected even if it is otherwise valid. The
default database file is database.db in the current directory.
*-f dbname*
Use dbname instead of default filename for double spend database.
*-p period*
Purges the database of expired tokens if the given time period has
passed since the last time it was purged. As a convenience *-p now*
is equivalent to *-p 0* both of which mean purge now, regardless of
when the database was last purged.
If used in combination with *-j resource* only the tokens minted for
the given resource are purged.
If used in combination with *-k* all tokens even un-expired tokens
are purged. Can be used in combination with *-t time* to expire as
if the current time were the given time.
*-k*
Use with option *-p* to request all tokens are purged rather than
just expired ones.
*-j resource*
Use with option *-p* to request that just tokens matching the given
resource name are to be purged, rather than the default which is to
purge all expired tokens. If the resource name is the empty string,
all tokens are matched (this is equivalent to omitting the *-j*
option).
*-s*
Print timing information only, and don't proceed to create a token.
If combined with *-b* flag print estimate of how long the requested
collision size would take to compute, if *-s* given by itself, just
prints speed of the collision finder.
*-h*
Print short usage information.
*-v*
Print more verbose informational output about the token minting or
verification. (If -v is the only argument, prints the tool version
number.)
*-q*
Batch mode. Prints no information other than output. This option
overrides the *-v* option.
*-X*
When minting, prints the hashcash email X-header 'X-Hashcash: '
before the token. Without this option just the bare token is
printed.
When checking, if no token is given as an argument, scans stdin for
a line starting with the string 'X-Hashcash:', and uses the rest of
the matching line as the token. Only the lines up to and ending at
the first blank line are scanned. A blank line is the separator used
to separate the headers from the body of a mail message or USENET
article. This is meant to make it convenient to pipe a mail message
or USENET article to hashcash on stdin.
*-x string*
Similar effect to *-X* for minting and checking except you get to
choose your own header string. For example *-x 'X-Hashcash: '* has
the same effect as *-X*.
*-i*
When checking and using the *-X* or *-x* flag, ignore the blank line
boundary between headers and body of the message, and check for
collision in the body too if one is not found in the headers.
*-t time*
Pretend the current time is the time given for purposes of minting
tokens, verifying tokens and purging old tokens from the database.
Time is given in a format based on UTCTIME format
YYMMDD[hh[mm[ss]]].
Time is expressed in local time by default. Use with *-u* flag to
give time in UTC (GMT).
You can also give time relative to the current time by prefixing the
argument with + or -. The default units for relative time are
seconds. A single character suffix can be used to specify alternate
units (m = minutes, h = hours, d = days, M = months, y = Y = years,
and s = seconds).
Note: when time is expressed in local time, if there is daylight
savings in your timezone, there are one or two ambiguous hours per
year at the time of change from daylight savings time to normal
time.
*-u*
Input and output absolute times in UTC (GMT) instead of local time.
*-a period*
Add (or subtract if number is negative) a random value from the
current time before minting the token. This hides the time the token
was created, which may be useful for anonymous users. Note adding
(rather than subtracting) a random time may be risky if the token
takes less than the added time to arrive as the recipient will
reject tokens with time stamps in the future.
*-n*
Print resource name parsed from token being verified. Returns exit
code unchecked on exit.
*-l*
Print number of seconds left before token expires. Returns exit code
unchecked on exit.
Note: the calculation includes the grace period, so can be up to 2
times grace period longer than you might otherwise expect (clock
fast but system has to presume it could be slow). If you want to
exclude the grace period add *-g0* to set grace period to 0 for the
calculation.
*-w*
Print number of bits of collision of token. Returns exit code
unchecked on exit.
*-y*
Returns success if the token is valid even if it is not fully
checked. Use with *-c* where not all of *-b*, *-d*, *-r* are
specified to get success exit code on valid but partially checked
token. Similarly can use with *-n*, *-l*, *-w* with same effect.
EXAMPLES
Creating tokens
"hashcash -s"
Print timing information about how many collisions the machine can
try per second.
"hashcash -s -b 32"
Print how long it would take the machine to compute a 32 bit
collision (but don't actually compute a collision).
"hashcash"
Mint a token. Will prompt for resource name and desired value
(number of collision bits).
"hashcash foo"
Compute collision on resource foo. Will prompt desired value (number
of collision bits).
"hashcash foo -b 10"
Compute 10 bit collision on resource foo.
"hashcash -a -3d"
Subtract a random time of between 0 days and 3 days to to the
token's creation time. This is the same fuzz factor used by
mixmaster to reduce risk of timing-correlations.
Examining Tokens
"hashcash -w 0:020814:foo:4333957e84db47f6"
Report the value of the token (how many bits of collision) there
are. The example is a 33 bit collision, which would take on average
13 hours to create on a 400 Mhz Pentium-II.
"hashcash -q -b 10 foo | hashcash -w"
Create a token in batch mode, pass to hashcash on stdin to verify,
have it print how many bits there were. Note: half of the time you
get a token 1 bit larger; similarly with decreasing probability you
can get even larger tokens.
"hashcash -n 0:020814:foo:21c8cf3099cbf467"
Report the resource name from the token. The resource name in the
example is foo.
"hashcash -l -e 30y 0:020814:foo:21c8cf3099cbf467"
Report how long until the token expires if it expires in 30 years
from it's creation date. (Note dates too far into the future run
into the 2038 end of Epoch, which is the unix time analog of the y2k
bug).
Verifying Tokens
"hashcash -c 0:020814:foo:21c8cf3099cbf467"
Check if the token is valid. Note as we are not checking the token
in a double spend database, and did not specify a resource name or
required number of bits of collision and hashcash will consider the
token not fully checked, and it will report it as valid but not
fully unchecked, or as invalid if there is any problem with the
token.
"hashcash -c -b24 0:020814:foo:21c8cf3099cbf467"
Check that the value of the token is greater or equal to 24 bits.
This example has 24 bit value. If you increase the requested number
of bits or replace the token with one with less than 24 bit
collision the token will be rejected.
"hashcash -c -b24 -r foo 0:020814:foo:21c8cf3099cbf467"
As above check if the token has sufficient value, but in addition
check that the resource name given matches the resource name in the
token.
Double Spending Prevention
The examples given in "Verifying Tokens" can be modified to keep a
double spend database so that the same token will not be accepted twice.
Note a token will only be checked in and added to the database if it is
otherwise valid and fully checked (a required number of bits of
collision has been specified and a resource has been specified).
"hashcash -cd -b 10 -r foo 0:020814:foo:21c8cf3099cbf467"
Check the token and add to double spent database if it's valid (has
correct resource name and sufficient value).
"hashcash -cd -b 10 -r foo 0:020814:foo:21c8cf3099cbf467"
Try to double spend the token. It will be rejected as double spent.
Token Expiry
To prevent the double spend database growing indefinately, the recipient
can request that tokens be no older than a specified period. After
expiry old tokens can dropped from the double spend database as they
will no longer be needed -- expired tokens can be rejected based purely
on their old date, so the space taken by expired tokens in the double
spend database can be saved without risk of accepting an expired though
otherwise valid token.
The first field of the token is the UTC time since 1st January 1970. The
default time format is YYMMDD, time rounded down to the nearest day. The
default validity period is 28 days.
You can provide an alternative validity period with the *-e* option.
"hashcash -cd -b 10 -e 2d -r foo 0:020811:foo:21dd87d4c9f5aae1"
Try verifying an old token, the above token was created 11 Aug 2002.
We gave option *-e 2d* so the tokens expiry date is 2 days after
creation, which is now in the past.
Note: if the creation time is expressed in the token in days, the
precise creation date is the begining of the specified day in UTC
time (similarly for alternate units the creation time is rounded
down to the begining of the unit it is expressed in). For units in
days, for example, this may mean depending on your time zone that
the token appears to be considered invalid in under the specified
expiry period in days relative to your relative view of what day it
is, as the calculation is based on current time in UTC, and the
creation time of the token is expressed in UTC time.
"hashcash -cd -b 10 -r foo 0:020811:foo:21dd87d4c9f5aae1"
Test whether the token is otherwise valid, apart from having
expired. Omitting the *-e* tells hashcash that the token will never
expire. An expiry period of forever can also be given explitly like
this: *-e 0*, where an expiry period of 0 means forever.
Purging old tokens
If the *-c*, *-d* options are used together, each time a token is
checked, if it is valid and all of the mandatory aspects of the token
are verified (collision bits check, resource name check) then the token
and it's expiry period is written to the database file. The default
expiry period if an expiry period is not given explicitly with the *-e*
option is forever (ie tokens do not expire).
First mint and then add a token:
"hashcash -b 10 foo -e 1m > token"
Note: we specified an expiry on minting in this example, to ensure
that the token creation time is given in high enough resolution in
the token that the token will not be considered expired at time of
creation. (Recall the default resolution is in days, a token created
with a creation time rounded down to the beginging of the day is
unlikely to be considered valid 1 minute later unless you mint it at
midnight UTC time.)
"hashcash -cd -e 1m -b 10 -r foo < token"
The token expires in 1 minute. Wait 1 minute and then explicitly
request that expired tokens be purged:
"hashcash -p now"
Then try resubmitting the same token:
"hashcash -cd -e 1m -b 10 -r foo < token"
and the token will be rejected anyway as it has expired,
illustrating why it was not necessary to keep this token in the
database.
With the default database (the sdb format) the database contents are
human readable, so you can view their contents by cating them to the
terminal:
"cat hashcash.db"
to see that the token really is added and then after puring
subsequently purged due to expiry.
Purging old tokens on Demand
As a convenience you can purge at the same time as checking tokens by
using the *-p* option with the *-c* option.
"hashcash -b 10 foo > token" =item "hashcash -cd -p now -e 1 -b 10 -r
foo < token"
It may be inefficient to purge tokens on every use as the entire
database has to be scanned for expired tokens. By giving a time
period to the *-p* option, you can tell "hashcash" to purge no more
frequently than that time period since the previous purge.
For example:
"hashcash -cd -p 1d -e 1 -b 10 -r foo < token"
tells "hashcash" to purge any expired tokens no more than once per
day.
"hashcash -p 1M -j foo"
tells "hashcash" to purge only expired tokens matching resource foo
once per month.
"hashcash -p now -k"
tells "hashcash" to purge all tokens (expired and unexpired) now.
token format
*ver*:*date*:*resource*:*collision*
where
*ver* = 0, this version of hashcash only supports version 0
*date* = YYMMDD[hh[mm[ss]]]
*resource* = resource string (eg IP address, email address)
*collision* = printable string of random alpha-numeric chars
FILES
hashcash.db
default double spend database
hashcash.dbt
default temporary double spend database used when purging tokens.
EXIT STATUS
"hashcash" returns success (exit code 0) after successfully minting a
token, after fully checking a token and finding it valid, and after a
timing test.
If when checking a token it is found to be invalid (due to being
malformed, being expired, having insufficient value, having a date in
the future, or being double spent), "hashcash" returns failure (exit
code 1).
If insufficient options are given to fully check a token, or if using
the *-n*, *-l*, or *-w* options, if the token is otherwise valid return
unchecked (exit code 2). If the *-y* flag is given and hashcash would
normally return unchecked, exit code success is returned instead.
If any exception occurs (file read failure for database checking or
corrupted database contents) an exit status of 3 is returned.
AUTHOR
Written by Adam Back
SEE ALSO
sha1(1), http://www.hashcash.org/