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();
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);
MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] s1 = sha.digest(pubBytes);
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.
byte[] shaFinal = sha.digest(sha.digest(ripeMDPadded));
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);
//base 58 encode
System.out.println("Bitcoin Address: " + Base58.encode(sumBytes));
You can validate the generated address.
Bitcoin Address: 1NWrUGmwNejuHYLEhH685BL5ugfFCZgco7
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));
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