Web3j创建钱包的2种方式的对比

今天和大家说说创建钱包的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密码设置为空密码。

也正是因为目前大多平台生成钱包时对其设置均为空字符串,所以我们通过助记词、私钥导入钱包的时候,是不需要密码的,让你填写的那个密码是重新设置的一个新密码。

好像突然间知道为什么私钥和助记词那么重要了,因为别人不需要密码就能控制你钱包的资产。

你可能感兴趣的:(Web3j创建钱包的2种方式的对比)