今天和大家说说创建钱包的2种方式的对比。
关于BIP
在创建钱包之前,我建议你先了解一下BIP32
,BIP39
,BIP44
.
这一部分,我先不细讲,后面会专门写一篇关于BIP协议的,大家先简单了解下。
BIP 全名是 Bitcoin Improvement Proposals,是提出 Bitcoin 的新功能或改进措施的文件。可由任何人提出,经过审核后公布在 bitcoin/bips 上。BIP 和 Bitcoin 的关系,就像是 RFC 之于 Internet。
而其中的 BIP32
,BIP39
,BIP44
共同定义了目前被广泛使用的 HD Wallet。
创建钱包的步骤
创建的钱包的流程为:
- 1、随机生成一组助记词
- 2、生成 一个种子seed
- 3、根据seed生成公钥、私钥、地址
- 4、根据公钥、 私钥、 密码生成钱包文件,也就是Keystore
/**
* generate a random group of mnemonics
* 生成一组随机的助记词
*/
private String generateMnemonics() {
StringBuilder sb = new StringBuilder();
byte[] entropy = new byte[Words.TWELVE.byteLength()];
new SecureRandom().nextBytes(entropy);
new MnemonicGenerator(English.INSTANCE)
.createMnemonic(entropy, sb::append);
return sb.toString();
}
/**
*
* 根据助记词和密码生成种子seed
*/
byte[] seed = new SeedCalculator().calculateSeed(generateMnemonics(), "");
/**
*
* 根据seed生成公钥、私钥等
*/
ECKeyPair ecKeyPair = ECKeyPair.create(Sha256.sha256(seed));
Numeric.toHexStringWithPrefix(ecKeyPair.getPrivateKey());
Numeric.toHexStringWithPrefix(ecKeyPair.getPublicKey());
//根据公钥或者ECKeyPair获取钱包地址
String address = Keys.getAddress(ecKeyPair);
/**
*
* 根据公钥 私钥 密码 得到 生成钱包文件keystore
*/
WalletFile walletFile = Wallet.createLight(password, keyPair);
第1,2步参考BIP39
这种方案算是正规流程中较为简洁的一种,很多项目大概也是这种思路,最多生成ECKeyPair那里略有差异。
另外一种简洁的方案
但是我在网上很多博客充斥着另外一种方案,这种方案生成钱包文件特别简单,但是我研究一番,发现是有问题的。
//第一个参数是密码,第二个参数是钱包存放的路径
Bip39Wallet wallet = WalletUtils.generateBip39Wallet("password",file)
//生成12个单词的助记词
String memorizingWords = wallet.getMnemonic();
//通过钱包密码与助记词获得钱包地址、公钥及私钥信息
Credentials credentials = WalletUtils.loadBip39Credentials(walletPwd,
wallet.getMnemonic());
String address = credentials.getAddress();
String publicKey = credentials.getEcKeyPair().getPublicKey().toString(16);
因为大多平台生成钱包时,在seed这里对其设置均为空字符串.,如果使用用户输入的密码作为其密码,这将使得钱包不能通用
通过查阅generateBip39Wallet()
这个方法的源码发现在生成种子seed的时候,它使用了生成助记词(也就是我们创建钱包)的那个密码,这就有问题了。
大家可以对比一下,通过助记词生成种子seed的那句代码,我的第二个参数,也就是密码,设置的是空字符串
/**
*
* 根据助记词和密码生成种子seed
*/
byte[] seed = new SeedCalculator().calculateSeed(generateMnemonics(), "");
这里有个注意点:
byte[] seed = new SeedCalculator().calculateSeed(mnemonics, "")
这里的""是BIP39的密码,.目前大多平台生成钱包时对其设置均为空字符串,只有少数平台生成钱包使用用户输入的密码作为其密码,这将使得钱包不能通用。
说到这里大家懂了吧,为了保证钱包的通用性,也就是说生成的助记词、私钥可以在别的钱包导入使用,那么你需要在生成seed的时候,把这个bip39密码设置为空密码。
也正是因为目前大多平台生成钱包时对其设置均为空字符串,所以我们通过助记词、私钥导入钱包的时候,是不需要密码的,让你填写的那个密码是重新设置的一个新密码。
好像突然间知道为什么私钥和助记词那么重要了,因为别人不需要密码就能控制你钱包的资产。