如何使用Java将Tron钱包助记词转换为私钥?
本来想着这个问题挺简单,可是查了半天,不是,不止半天查了好长时间,看了半天官网文档,全网Java就没有实现的。
咋办。。。咋办呢?
好巧,官网我看到了一个Tronweb的东东。
呦呵。。。再细细的看下,找到一个接口。
fromMnemonic
但是咱们这个Tronweb是前端项目啊,先不管了,我们来先看是否能实现,然后看看Js的实现是否能转换为Java语言。
创建完Vue项目,我们来导入TronWeb
npm install tronweb
写一个简单的vue来实现,我在想:Tron可以离线创建私钥、地址以及助记词。它的生成也是加密解密的关系,那么这里我们使用tronweb其实并不需要实例化,只要引入它的组件包,包含加解密应该就行了,那么代码其实很简单。
// 导入
import Tronweb from "tronweb";
// 直接调用接口查看
Tronweb.fromMnemonic(this.zjc)
写web我们就必须要可视化,那么我们写一个简单的页面。
输入助记词,点击解析后,我们看等到了私钥、公钥还有地址信息。
那么让我们来分析一下他的实现:
import {ethersHDNodeWallet, Mnemonic} from './ethersUtils'
const account = ethersHDNodeWallet.fromMnemonic(Mnemonic.fromPhrase(mnemonic, null, wordlist), path);
const result = {
mnemonic: account.mnemonic,
privateKey: account.privateKey,
publicKey: account.signingKey.publicKey,
address: pkToAddress(account.privateKey.replace(/^0x/, ''))
}
看到实际的实现是ethersHDNodeWallet、Mnemonic俩个类。然后我们再看下ethersUtils那的实现。
import {
Mnemonic,
HDNodeWallet as ethersHDNodeWallet
} from 'ethers';
看到ethers,这里我们就可以知道了。
哦,原来Tron波场链其实也是以太坊的分支链,那么按照理论上来说Tron的加解密方式其实也是ETH的加密方式。
看到了这里,我们这里转到Java。
先理解下ETH创建离线地址的过程:
1.生成一个随机的助记词
2.使用助记词生成一串种子
3.进行路径(BIP30)加密后产出地址等信息。
那么现在我们已经有了助记词,是不是直接用当前的助记词来生成种子,就可以产出私钥、地址等了呢?
publicstatic void main(String[] args) {
String mnemonic = "program repair next claw rival slight spider tennis begin cute daring fancy";
//使用助记词生成钱包种子
List<String> mnemonics = Splitter.on(" ").splitToList(mnemonic);
System.out.println(mnemonics.get(0));
byte[] seed = MnemonicCode.toSeed(mnemonics, "");
DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
DeterministicHierarchy deterministicHierarchy = new DeterministicHierarchy(masterPrivateKey);
DeterministicKey deterministicKey = deterministicHierarchy
.deriveChild(BIP44_ETH_ACCOUNT_ZERO_PATH, false, true, new ChildNumber(0));
byte[] bytes = deterministicKey.getPrivKeyBytes();
ECKeyPair keyPair = ECKeyPair.create(bytes);
System.out.println("0x" + keyPair.getPrivateKey().toString(16));
}
运行程序后,结果是错的。
那么到底是哪里错了呢?
再看看代码前面的TronWeb接口:
哦哦哦。。。原来的path是BIP44(m/44'/195'/0'/0/0),那么我们把这个Path参数修改下,看是否可行?
之前试了好几次,都没有达到最终正确的生成。
快要绝望的时候,我直接按了一下IDEA的快捷键俩下SHIFT+SHIFT,有了新的机会!
这不是我要找的工具类吗?打开类看了它的内部实现,其实还不能完全适用,但是逻辑咱们清楚了,我们就来实现吧
public static final int HARDENED_BIT = 0x80000000;
public static void main(String[] args) throws MnemonicException.MnemonicLengthException {
String mnemonic = "program repair next claw rival slight spider tennis begin cute daring fancy";
byte[] seed = MnemonicUtils.generateSeed(mnemonic, "");
Bip32ECKeyPair masterKeypair = Bip32ECKeyPair.generateKeyPair(seed);
// m/44'/195'/0'/0/0
final int[] path = {44 | HARDENED_BIT, 195 | HARDENED_BIT, 0 | HARDENED_BIT, 0, 0};
Bip32ECKeyPair bip44Keypair = Bip32ECKeyPair.deriveKeyPair(masterKeypair, path);
Credentials credentials = Credentials.create(bip44Keypair);
String privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16);
System.out.println(privateKey);
KeyPair keyPair = new KeyPair(privateKey);
String base58CheckAddress = keyPair.toBase58CheckAddress();
String publicKey = keyPair.toPublicKey();
System.out.println(publicKey);
System.out.println(base58CheckAddress);
}
运行结果正确,完美。
解决这个问题其实花了好长时间,查百度、Google还有官网接口文档,部署开发Web前端的解决方案,试图找到门路。
写到这里,可以能帮到其他开发人员。
假如还是没有办法实现,关注我,联系我,帮您解决。