Javascript Hashcash Proof of Work

Suppose that you developed an app that will give users free stuff when they click a button. Obviously, there’s nothing stopping one user from spamming the button one million times and collecting a whole bunch of free stuff. If you wanted to prevent that, you could use something like a CAPTCHA, or perhaps give each user a session and cool off period. You could also implement something called a proof of work system.

If you have been reading up on Bitcoin and blockchain, then you are probably familiar with the idea of “proof of work.” Proof of work (POW) is a measure that a program or system can implement to deter malicious users from performing Dos attacks or spamming the program’s resources. Essentially, it forces the user to perform some complex and energy costing calculation before they are able to access the resource. Once the calculation is performed, the answer could be easily verified by other nodes on the network. When dealing with cryptocurrency this is essential because it prevents a computer from spamming the blockchain with a bunch of invalid new blocks.

The most popular proof of work system is the hashcash proof of work. This proof of work system requires the computer to find a hash of a plaintext string combined with an arbitrary piece of data (nonce) to make a hash that begins with a certain number of zeros. For example, say we have the string “cat.” Let’s say that then creates a hash of “abchdlerfergh” using the SHA-256 hash scheme. However, we want the hash to start with three zeroes so it will be “000ehbskfjek.” What we will do is take a number starting at 0, then hash it with out plaintext string and see if it gives us the desired output. If it doesn’t, we will increase the number until it does. A javascript hashcash proof of work implementation would work the exact same way since we are essentially just taking advantage of the crpyto library in NodeJS.

Javascript Hashcash Proof of Work

For this, we will be using NodeJS. Let’s begin by importing the crypto library:

const crypto = require('crypto');

Next, we will create a function to generate a string that will be approximately 1 MB. This will be our plaintext data that we will hash.

function randomChallengeString() {
 let longString = '';
 for (let i = 0; i < 1000000; i += 1) {
  longString += Math.random().toString(36).substr(2, 1);
 }
 return longString;
}

Finally, let’s create a function that will continously loop until we find a hasht hat begins with three zeroes. Once we find it, we will print out the answer.

(function doWork() {
 const challengeString = randomChallengeString();
 let nonce = 0;
 const startDate = new Date();
 let hash = crypto.createHash('sha256').update(challengeString + nonce).digest('hex');
 while (hash.substr(0, 3) !== '000') {
  hash = crypto.createHash('sha256').update(challengeString + nonce).digest('hex');
  nonce += 1;
 }
 const endDate = new Date();
 console.log('Found the answer');
 console.log(`The answer is ${nonce} with a final hash of ${hash}`);
 console.log(`${(endDate - startDate) / 1000} seconds to complete`);
}());

Once it’s done, you should get an output that looks like this:

Now keep in mind, Bitcoin looks for a hash that begins with about 17 zeroes. So compared to bitcoin this is pretty easy. Obviously, the more zeroes that you look for, the longer this will take to complete.

You can find the full project over on GitHub.