Generate Bitcoin Wallet Address in Java

Generate Bitcoin Wallet Address in Java

Generate Key Pair

Generate Key Pair with ECDSA Algorithm


ECGenParameterSpec ecSpec = new ECGenParameterSpec(SPEC);
KeyPairGenerator g = KeyPairGenerator.getInstance("EC");
g.initialize(ecSpec, new SecureRandom());
KeyPair keypair = g.generateKeyPair();
PublicKey publicKey = keypair.getPublic();
PrivateKey privateKey = keypair.getPrivate();

Public Key

Take the corresponding public key generated with it (33 bytes, 1 byte 0x02 (y-coord is even), and 32 bytes corresponding to X coordinate)

ECPublicKey epub = (ECPublicKey) publicKey;
ECPoint pt = epub.getW();
byte[] pubBytes = new byte[33]; //32 + 1
pubBytes[0] = 2; //0x02
System.arraycopy(pt.getAffineX().toByteArray(), 0, pubBytes, 1, 32);

SHA-256

MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] s1 = sha.digest(pubBytes);

RIPEMD-160

Ripemd160.java file is used here.

RIPEMD-160 generates 20 bytes hash. We will append an extra one byte.

byte[] ripeMD = Ripemd160.getHash(s1);

//adds 0x00
byte[] ripeMDPadded = new byte[ripeMD.length + 1];
ripeMDPadded[0] = 0;

System.arraycopy(ripeMD, 0, ripeMDPadded, 1, 1);

Here the total ripeMDPadded size is 21 bytes.

Repeat SHA 256 twice

byte[] shaFinal = sha.digest(sha.digest(ripeMDPadded));

RIPEMD-160 Plus SHA256 (4 Bytes)

RIPEMD-160 is attached to 4 bytes of SHA256 second hash.

//add check sum
byte[] sumBytes = new byte[25];
System.arraycopy(ripeMDPadded, 0, sumBytes, 0, 21);
System.arraycopy(shaFinal, 0, sumBytes, 21, 4);

Base58 Encode

//base 58 encode
System.out.println("Bitcoin Address: " + Base58.encode(sumBytes));

Output

You can validate the generated address.

Bitcoin Address: 1NWrUGmwNejuHYLEhH685BL5ugfFCZgco7

Code


ECGenParameterSpec ecSpec = new ECGenParameterSpec(SPEC);
KeyPairGenerator g = KeyPairGenerator.getInstance("EC");
g.initialize(ecSpec, new SecureRandom());
KeyPair keypair = g.generateKeyPair();
PublicKey publicKey = keypair.getPublic();
PrivateKey privateKey = keypair.getPrivate();

ECPublicKey epub = (ECPublicKey) publicKey;
ECPoint pt = epub.getW();
byte[] bcPub = new byte[33];
bcPub[0] = 2;
System.arraycopy(pt.getAffineX().toByteArray(), 0, bcPub, 1, 32);

MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] s1 = sha.digest(bcPub);

byte[] ripeMD = Ripemd160.getHash(s1);

//add 0x00
byte[] ripeMDPadded = new byte[ripeMD.length + 1];
ripeMDPadded[0] = 0;

System.arraycopy(ripeMD, 0, ripeMDPadded, 1, 1);

byte[] shaFinal = sha.digest(sha.digest(ripeMDPadded));

//append ripeMDPadded + shaFinal = sumBytes
byte[] sumBytes = new byte[25];
System.arraycopy(ripeMDPadded, 0, sumBytes, 0, 21);
System.arraycopy(shaFinal, 0, sumBytes, 21, 4);

//base 58 encode
System.out.println("Bitcoin Address: " + Base58.encode(sumBytes));              

Reference

For Bitcoin address format

https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses

For RIPEMD-160

https://github.com/nayuki/Bitcoin-Cryptography-Library/blob/master/java/io/nayuki/bitcoin/crypto/Ripemd160.java