BIP32/BIP39/BIP44 HD Wallet

import lombok.extern.slf4j.Slf4j;
import org.bitcoinj.crypto.*;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.wallet.DeterministicSeed;
import org.junit.Test;
import org.web3j.crypto.ECKeyPair;
import org.web3j.crypto.Keys;

import java.io.IOException;
import java.security.SecureRandom;
import java.util.List;

/**
 * 

* *

* * @author: flx * @date: 2018/8/28 16:52 * @description: 生成mnemonic > 生成seed > 生成 Extended Public Key * 生成地址主要依赖Extended Public Key,加上addressIndex(0至232-1)就可以确定一个地址. * BTC使用m/44’/0’/0’/0的 Extended Public Key 生成 m/44’/0’/0’/0/*, * ETH使用m/44’/60’/0’/0的 Extended Public Key 生成 m/44’/60’/0’/0/*, * mainnet的Extended Public Key以xpub做前缀 * 验证网址:https://iancoleman.io/bip39/ */ @Slf4j public class TestBip { private static final String C_BLANK1 = " "; private static final String PREFIX = "0x"; private static final byte[] SEED = null; private static final String PASSPHRASE = ""; private static final Long CREATIONTIMESECONDS = 0L; /** * TestNet3Params(公共测试网络)/RegTestParams(私有测试网络)/MainNetParams(生产网络) */ private static final MainNetParams mainnetParams = MainNetParams.get(); @Test public void TestBip44ETH() throws Exception { String wordList = this.getWordListString(); wordList = "please promote sting series horn leave squirrel juice harsh over wash reduce"; log.info("generate mnemonic code:[{}]", wordList); DeterministicSeed deterministicSeed = new DeterministicSeed(wordList, SEED, PASSPHRASE, CREATIONTIMESECONDS); log.info("BIP39 seed:{}", deterministicSeed.toHexString()); /**生成根私钥 root private key*/ DeterministicKey rootPrivateKey = HDKeyDerivation.createMasterPrivateKey(deterministicSeed.getSeedBytes()); /**根私钥进行 priB58编码*/ String priv = rootPrivateKey.serializePrivB58(mainnetParams); log.info("BIP32 extended private key:{}", priv); /**由根私钥生成HD钱包*/ DeterministicHierarchy deterministicHierarchy = new DeterministicHierarchy(rootPrivateKey); /**定义父路径*/ List parsePath = HDUtils.parsePath("44H/60H/0H"); DeterministicKey accountKey0 = deterministicHierarchy.get(parsePath, true, true); log.info("Account extended private key:{}", accountKey0.serializePrivB58(mainnetParams)); log.info("Account extended public key:{}", accountKey0.serializePubB58(mainnetParams)); /**由父路径,派生出第一个子私钥*/ DeterministicKey childKey0 = HDKeyDerivation.deriveChildKey(accountKey0, 0); // DeterministicKey childKey0 = deterministicHierarchy.deriveChild(parsePath, true, true, new ChildNumber(0)); log.info("BIP32 extended 0 private key:{}", childKey0.serializePrivB58(mainnetParams)); log.info("BIP32 extended 0 public key:{}", childKey0.serializePubB58(mainnetParams)); log.info("0 private key:{}", childKey0.getPrivateKeyAsHex()); log.info("0 public key:{}", childKey0.getPublicKeyAsHex()); ECKeyPair childEcKeyPair0 = ECKeyPair.create(childKey0.getPrivKeyBytes()); log.info("0 address:{}", PREFIX + Keys.getAddress(childEcKeyPair0)); /**由父路径,派生出第二个子私钥*/ DeterministicKey childKey1 = HDKeyDerivation.deriveChildKey(accountKey0, 1); log.info("BIP32 extended 1 private key:{}", childKey1.serializePrivB58(mainnetParams)); log.info("BIP32 extended 1 public key:{}", childKey1.serializePubB58(mainnetParams)); log.info("1 private key:{}", childKey1.getPrivateKeyAsHex()); log.info("1 public key:{}", childKey1.getPublicKeyAsHex()); ECKeyPair childEcKeyPair1 = ECKeyPair.create(childKey1.getPrivKeyBytes()); log.info("1 address:{}", Keys.toChecksumAddress(Keys.getAddress(childEcKeyPair1))); String address1 = Keys.getAddress(childKey1.decompress().getPublicKeyAsHex().substring(2)); log.info("1 address:{}", Keys.toChecksumAddress(address1)); } @Test public void TestBip44BTC() throws Exception { String wordList = this.getWordListString(); wordList = "please promote sting series horn leave squirrel juice harsh over wash reduce"; log.info("generate mnemonic code:[{}]", wordList); DeterministicSeed deterministicSeed = new DeterministicSeed(wordList, SEED, PASSPHRASE, CREATIONTIMESECONDS); log.info("BIP39 seed:{}", deterministicSeed.toHexString()); /**生成根私钥 root private key*/ DeterministicKey rootPrivateKey = HDKeyDerivation.createMasterPrivateKey(deterministicSeed.getSeedBytes()); /**根私钥进行 priB58编码*/ String priv = rootPrivateKey.serializePrivB58(mainnetParams); log.info("BIP32 extended private key:{}", priv); /**由根私钥生成HD钱包*/ DeterministicHierarchy deterministicHierarchy = new DeterministicHierarchy(rootPrivateKey); /**定义父路径*/ List parsePath = HDUtils.parsePath("44H/0H/0H"); DeterministicKey accountKey0 = deterministicHierarchy.get(parsePath, true, true); log.info("Account extended private key:{}", accountKey0.serializePrivB58(mainnetParams)); log.info("Account extended public key:{}", accountKey0.serializePubB58(mainnetParams)); /**由父路径,派生出第一个子私钥*/ DeterministicKey childKey0 = HDKeyDerivation.deriveChildKey(accountKey0, 0); // DeterministicKey childKey0 = deterministicHierarchy.deriveChild(parsePath, true, true, new ChildNumber(0)); log.info("BIP32 extended 0 private key:{}", childKey0.serializePrivB58(mainnetParams)); log.info("BIP32 extended 0 public key:{}", childKey0.serializePubB58(mainnetParams)); log.info("0 private key:{}", childKey0.getPrivateKeyAsHex()); log.info("0 public key:{}", childKey0.getPublicKeyAsHex()); log.info("0 address:{}", childKey0.toAddress(mainnetParams)); /**由父路径,派生出第二个子私钥*/ DeterministicKey childKey1 = HDKeyDerivation.deriveChildKey(accountKey0, 1); log.info("BIP32 extended 1 private key:{}", childKey1.serializePrivB58(mainnetParams)); log.info("BIP32 extended 1 public key:{}", childKey1.serializePubB58(mainnetParams)); log.info("1 private key:{}", childKey1.getPrivateKeyAsHex()); log.info("1 public key:{}", childKey1.getPublicKeyAsHex()); log.info("1 address:{}", childKey1.toAddress(mainnetParams)); } /** * 生成12个助记词 * * @return * @throws IOException * @throws MnemonicException.MnemonicLengthException */ public String getWordListString() throws IOException, MnemonicException.MnemonicLengthException { StringBuilder stringBuilder = new StringBuilder(); getWordList().stream().forEach(word -> { stringBuilder.append(word).append(C_BLANK1); }); return stringBuilder.toString().trim(); } /** * 生成12个助记词 * * @return * @throws IOException * @throws MnemonicException.MnemonicLengthException */ public List getWordList() throws IOException, MnemonicException.MnemonicLengthException { MnemonicCode mnemonicCode = new MnemonicCode(); SecureRandom secureRandom = new SecureRandom(); /**必须是被4整除*/ byte[] initialEntropy = new byte[16]; secureRandom.nextBytes(initialEntropy); return mnemonicCode.toMnemonic(initialEntropy); } }

参考链接:

https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki

https://github.com/bitsofproof/supernode/blob/1.1/api/src/main/java/com/bitsofproof/supernode/api/ExtendedKey.java

https://github.com/bushidowallet/bushido-java-core/tree/master/src/main/java/com/bushidowallet/core/bitcoin/bip32

测试链接:https://iancoleman.io/bip39/

你可能感兴趣的:(blockchain,BIP32,BIP39,BIP44)