007 / hashcash-js

Generic javascript implementation of hashcash
http://geekportfolio.com/casestudy/hashcash.xhtml
52 stars 7 forks source link

Hashcash for PHP/JavaScript forms

Hashcash works by requiring the client to perform a complex calculation before the server will accept its input. Although the calculation may take the client several seconds to process, the server can check the results almost instantly.

The process is easiest to explain using square roots. Given the number 332,929, it takes about 36 steps for a computer to find its square root of 577. However, once the root is found, it only takes one step to test if the result is correct — check to see that 577 * 577 = 332,929. Hashcash doesn’t use square roots for its calculations, but it does work by the same principle.

In a Hashcash transaction, the server generates a string called a stamp that contains encoded information about the client. Specifically, it includes the current time at the server, and the IP address from which the client is accessing the server. The data also includes a salt value (described below), and is encoded using a hash function (in this case, CRC32).

Salt values, commonly used in encryption functions, are used to increase the amount of processing that an attacker would have to expend to "crack" some data. They are simply random data that is added to the information being encrypted to make reversing the process harder.

Without salts, an attacker will know their IP address and can calculate a large number of stamps before launching an attack.

With the addition of the salt value, the attacker would not have the information necessary to calculate correct stamp values, even if they could correctly identify the server time and their own IP address. Thusly, every time the server generates a new stamp, the attacker is forced to start over.

If the same salt value is used in two different implementations, the hash values generated will match between the two. An attacker who saw that two different sites that use this protection generated similar stamps, they would only have to expend effort to bypass one of the sites in order to gain access to both. If, instead, the two sites used different salts, the attacker would have to expend twice the effort to access both sites. With this property in mind, the salt values should be changed to a different random string for each client this script is installed upon.

Step-by-step

There are two parties to a hashcash transaction, client and server.

Hc config file — 4 params

TODO: what is this?

JAVASCRIPT DOCUMENTATION

hc_HashFunc should be defined in its own script, wherever the function itself is created. It should take one parameter (a string) and return a hex string as its output. In the current implementation I use CRC32, but any hash function that has both a JavaScript and a server-side implementation that return the same results for the same input data will work. MD5 was tested, but was too slow for the client side. Depending on your exact circumstances you may want to use some other function, but the included version should work for most implementations.

// set form element x to value y

function hc_SetFormData(x, y)

// return value of form element x

function hc_GetFormData(x)

// convert hex numbers to binary strings

function hc_HexInBin(x)

// returns a string of num_bits from hex_string

function hc_ExtractBits(hex_string, num_bits)

// checks col_string vs. pg_sbits for pg_contract bits

function hc_CheckContract(pg_contract, pg_sbits, col_string)

// generate a random string of length x using [0-9A-Za-z]

function hc_GenChars(x)

// extracts data from page to calculate hash collision

function hc_SpendHash()

PHP DOCUMENTATION

// define generic hash function (currently crc32)

function hc_HashFunc($x) { return sprintf("%08x", crc32($x)); }

// convert hex numbers to binary strings

function hc_HexInBin($x)

// get the first $num_bits bits of $hex_string

function hc_ExtractBits($hex_string, $num_bits)

// generate a stamp based on IP, time and salt

// embeds hc_stamp, hc_contract and hc_collision in the form

function hc_CreateStamp()

// hc_CheckExpiration - true = valid, false = expired

function hc_CheckExpiration($a_stamp)

// check for collision of $stamp_contract bits for $stamp and $collision

function hc_CheckContract($stamp, $collision, $stamp_contract)

// checks validity, expiration, and contract obligations for a stamp

function hc_CheckStamp()

Still ToDo