有遇到疑惑的可加QQ群交流:1057160243
以太坊地址生成过程如下:
- 生成 256 位随机数作为私钥。
- 将私钥转化为 secp256k1 非压缩格式的公钥,即 512 位的公钥。
- 使用散列算法 Keccak256 计算公钥的哈希值,转化为十六进制字符串。
- 取十六进制字符串的后 40 个字母,开头加上 0x 作为地址。
直接上代码,代码里面有详细解释
/**
* 通用的以太坊基于bip44协议的助记词路径 (imtoken jaxx Metamask myetherwallet)
*/
private static String ETH_TYPE = "m/44'/60'/0'/0/0";
public Object createAddress(String password, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (password.length() < 12) {
return ResponseBuilder.custom().success("error", 500).data("password长度最少12位数").build();
}
// 生成助记词
EthHDWallet generateMnemonic = generateMnemonic(ETH_TYPE, password);
// 钱包地址
String address = generateMnemonic.Address;
// keystore
String keystore = generateMnemonic.keystore;
// 私要
String privateKey = generateMnemonic.privateKey;
// 公钥
String publicKey = generateMnemonic.publicKey;
// 助记词
List<String> mnemonic = generateMnemonic.mnemonic;
// 助记词字符串
String memorizing = Arrays.toString(mnemonic.toArray());
// 助记词路径
String mnemonicPath = generateMnemonic.mnemonicPath;
// 根私钥
String seedBytes = generateMnemonic.seedBytes;
// 助记词种子
String mnemonicSeedBytes = generateMnemonic.mnemonicSeedBytes;
Map<String,Object> map = new HashMap<>();
map.put("address",address.toString());
map.put("keystore", keystore);
map.put("memorizing",memorizing);
map.put("mnemonicPath",mnemonicPath);
map.put("mnemonicSeedBytes",mnemonicSeedBytes);
map.put("privateKey",privateKey);
map.put("publicKey",publicKey);
map.put("seedBytes",seedBytes);
return ResponseBuilder.custom().success("success", 0).data(map).build();
}
public static EthHDWallet generateMnemonic(String path, String password) {
if (!path.startsWith("m") && !path.startsWith("M")) {
// //参数非法
return null;
}
String[] pathArray = path.split("/");
if (pathArray.length <= 1) {
//内容不对
return null;
}
if (password.length() < 8) {
//密码过短
return null;
}
String passphrase = "";
long creationTimeSeconds = System.currentTimeMillis() / 1000;
DeterministicSeed ds = new DeterministicSeed(secureRandom, 128, passphrase);
return createEthWallet(ds, pathArray, password);
}
private static EthHDWallet createEthWallet(DeterministicSeed ds, String[] pathArray, String password) {
//根私钥
byte[] seedBytes = ds.getSeedBytes();
String seedBytesa = Arrays.toString(seedBytes);
//助记词
List<String> mnemonic = ds.getMnemonicCode();
String mnemonicSeedBytesa = null;
try {
//助记词种子
byte[] mnemonicSeedBytes = MnemonicCode.INSTANCE.toEntropy(mnemonic);
mnemonicSeedBytesa = Arrays.toString(mnemonicSeedBytes);
ECKeyPair mnemonicKeyPair = ECKeyPair.create(mnemonicSeedBytes);
WalletFile walletFile = Wallet.createLight(password, mnemonicKeyPair);
ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
//存这个keystore 用完后删除
String jsonStr = objectMapper.writeValueAsString(walletFile);
//验证
WalletFile checkWalletFile = objectMapper.readValue(jsonStr, WalletFile.class);
ECKeyPair ecKeyPair = Wallet.decrypt(password, checkWalletFile);
byte[] checkMnemonicSeedBytes = Numeric.hexStringToByteArray(ecKeyPair.getPrivateKey().toString(16));
List<String> checkMnemonic = MnemonicCode.INSTANCE.toMnemonic(checkMnemonicSeedBytes);
} catch (MnemonicException.MnemonicLengthException | MnemonicException.MnemonicWordException | MnemonicException.MnemonicChecksumException | CipherException | IOException e) {
e.printStackTrace();
}
if (seedBytes == null) {
return null;
}
DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes);
for (int i = 1; i < pathArray.length; i++) {
ChildNumber childNumber;
if (pathArray[i].endsWith("'")) {
int number = Integer.parseInt(pathArray[i].substring(0,
pathArray[i].length() - 1));
childNumber = new ChildNumber(number, true);
} else {
int number = Integer.parseInt(pathArray[i]);
childNumber = new ChildNumber(number, false);
}
dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
}
ECKeyPair keyPair = ECKeyPair.create(dkKey.getPrivKeyBytes());
EthHDWallet ethHDWallet = null;
try {
WalletFile walletFile = Wallet.createLight(password, keyPair);
ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
//存
String keystore = objectMapper.writeValueAsString(walletFile);
ethHDWallet = new EthHDWallet(keyPair.getPrivateKey().toString(16),
keyPair.getPublicKey().toString(16),
mnemonic, dkKey.getPathAsString(),
"0x" + walletFile.getAddress(), keystore, seedBytesa, mnemonicSeedBytesa);
} catch (CipherException | JsonProcessingException e) {
e.printStackTrace();
}
return ethHDWallet;
}
public static class EthHDWallet {
String privateKey;
String publicKey;
List<String> mnemonic;
String mnemonicPath;
String Address;
String keystore;
String seedBytes;
String mnemonicSeedBytes;
public EthHDWallet(String privateKey, String publicKey, List<String> mnemonic, String mnemonicPath, String address, String keystore, String seedBytes, String mnemonicSeedBytes) {
this.privateKey = privateKey;
this.publicKey = publicKey;
this.mnemonic = mnemonic;
this.mnemonicPath = mnemonicPath;
this.Address = address;
this.keystore = keystore;
this.seedBytes = seedBytes;
this.mnemonicSeedBytes = mnemonicSeedBytes;
}
}
依赖包
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.14.6</version>
<scope>compile</scope>
</dependency>
相关知识:
BIP32
定义 Hierarchical Deterministic wallet (简称 “HD Wallet”中文为分层确定性钱包),是一个系统可以从单一个 seed 产生一树状结构储存多组 keypairs(私钥和公钥)。好处是可以方便的备份、转移到其他相容装置(因为都只需要 seed),以及分层的权限控制等。
BIP39
将 seed 用方便记忆和书写的单字表示。业界一般使用 12 、15、18、21个单字组成的单词,,中文称为助记词或助记码。
BIP44
基于 BIP32 的系统,赋予树状结构中的各层特殊的意义。让同一个 seed 可以支援多币种、多帐户等。
可以通过特定的路径解析不同币种钱包,
btc一般是 m/44'/0'/0'/0eth一般是 m/44'/60'/0'/0
有遇到疑惑的可加QQ群交流:1057160243