How to create Bitcoin Addresses in Node.JS Cryptographically

in #bitcoin7 years ago (edited)

In my spare time I strive to learn, Learning is without doubt my favourite hobby. In the past week I decided to turn my attention to Node.JS, A framework for JavaScript that allows access to the Windows API and some filesystem functions. I am not the best at putting information across but I would like to share my findings in case it may help anyone. Please be patient and feel free to ask me for clarification.

Now, I wont go through the basics of install Node.JS, It is my assumption that you already have it.

Bitcoin addresses are created using elliptic-curve cryptography, I dont claim to be an expert at cryptography, I know a little to get by for personal use. So I wont go into this much. I would suggest reading the bitcoin.org developer reference to look into how Bitcoin utilises this. 

So lets start with the actual code.

Step 1. We will need some Node.JS packages to be able to do some cryptographic functions like hashing.

Create a new directory, Go to that directory in command prompt or terminal.

npm install --save crypto elliptic ripemd160 bs58 buffer

Step 2. Once we have these packages installed we can go ahead and code.

Create a new file in the same directory as the node_modules folder called index.js

Step 3. We need to require our dependencies so that we are able to use them.

At the top of index.js

const crypto = require('crypto');
const EC = require('elliptic').ec;
const RIPEMD160 = require('ripemd160');
const bs58 = require('bs58');
const buffer = require('buffer');
const ec = new EC('secp256k1');

function hasha256(data) {
   return crypto.createHash('sha256').update(data).digest();
} // A small function I created as there is a lot of sha256 hashing.

Step 4. We will also need to add some extra information specific to Bitcoin

const addrVer = Buffer.alloc(1, 0x00); // 0x00 P2PKH Mainnet, 0x6f P2PKH Testnet
const wifByte = Buffer.alloc(1, 0x80); // 0x80 Mainnet, 0xEF Testnet

The buffer library allows us  to work with bytes. We are creating 1 byte with Bitcoin specifics.

Step 5. Generate Public / Private Keys

var key = ec.genKeyPair();

var privKey = key.getPrivate().toString('hex');
var pubPoint = key.getPublic();
var x = pubPoint.getX(); // elliptic x
var y = pubPoint.getY(); // elliptic y

Step 6. Now we will turn the hex based private key into bytes using buffer and add our wifByte from step 4 onto the front of the private key.

var bufPrivKey = Buffer.from(privKey, 'hex');
var wifBufPriv = Buffer.concat([wifByte, bufPrivKey], wifByte.length + bufPrivKey.length);

Buffer.concat with concatenate (link/join) the two byte strings together.

Step 7. Now we will finish creating our private key in WIF format (Wallet Import Format)

var wifHashFirst = hasha256(wifBufPriv);
var wifHashSecond = hasha256(wifHashFirst);
var wifHashSig = wifHashSecond.slice(0, 4);
var wifBuf = Buffer.concat([wifBufPriv, wifHashSig], wifBufPriv.length + wifHashSig.length);
var wifFinal = bs58.encode(wifBuf);

We first hash the wifBufPriv concatenated byte string from step 6. We then hash again. We take 4 bytes for the signature. Then we add the signature to the end of the concatenated byte string from step 6.

Finally we encode our final byte string in base58. We now have a WIF key.

Step 8. Now we will move on to creating the Public key in a Bitcoin format.

var publicKey = pubPoint.encode('hex');
var publicKeyInitialHash = hasha256(Buffer.from(publicKey, 'hex'));
var publicKeyRIPEHash = new RIPEMD160().update(Buffer.from(publicKeyInitialHash, 'hex')).digest('hex');

var hashBuffer = Buffer.from(publicKeyRIPEHash, 'hex');
var concatHash = Buffer.concat([addrVer, hashBuffer], addrVer.length + hashBuffer.length);
var hashExtRipe = hasha256(concatHash);
var hashExtRipe2 = hasha256(hashExtRipe);
var hashSig = hashExtRipe2.slice(0, 4);
var bitcoinBinaryStr = Buffer.concat([concatHash, hashSig], concatHash.length + hashSig.length);

All the above code hashes the public key multiple times, Joins the address version for mainnet set in step 4.

Step 9. We are now ready to print our private key in WIF format and our public Bitcoin address.

var bitcoinWifAddress = wifFinal.toString('hex');
var bitcoinAddress = bs58.encode(Buffer.from(bitcoinBinaryStr));

After this lets create 2 console.log statements to print our keys.

console.log("WIF Private Key : %s", bitcoinWifAddress.toString('hex'));
console.log("Bitcoin Address : %s", bitcoinAddress.toString('hex'));

So now our final code looks like this https://pastebin.com/ULaX59fF

Lets run our program

D:\Dev\Node\Addr>node index.js
WIF Private Key : 5J8HacMzXqfoX27RpGHsYHsCNcVJJtcD65k9WCUwJJawraA2hUv
Bitcoin Address : 1G91P27MhZAiTnevEQRLok11uXTZUX8EtP

You can see an image here https://imgur.com/DvpaTGy

I hope this has been useful for some people, I know my teaching skills are not great and I am still learning node myself. Please leave any constructive criticism or comments. Share the knowledge :)

dlystyr

Sort:  

Congratulations @dlystyr! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

You published your First Post
You made your First Vote

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Congratulations @dlystyr! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.18
TRX 0.14
JST 0.030
BTC 58613.96
ETH 3153.58
USDT 1.00
SBD 2.43