区块链钱包“BTC,TRX,ETH”地址生成、助记词导入、keyStron文件生成等功能

avatar
作者
筋斗云
阅读量:2

一、前言

#最近闲着没事做,然后看听到说什么BTC疯涨,这类的小道消息。

         哦豁~,这一下就让我觉得非常好奇,说,他们这些东西是怎样在链上存在的呢,然后他们那个一串串的地址又是啥,imtoken钱包又是怎么实现的呢。

        根据以上疑问,我自己去研究,自己去做一个钱包可以不?PS:主要是这个问题简单点,那些什么在链上存在的我没研究透。

好的鸣人不说暗话,我们开始!


        

二、理解区块钱包

        首先我们得知道传说中的imtoken,web3等钱包是什么东西,它实际上就是一个以地址为核心的一个软件

ps:当然现在他们也有很多其他的功能,比如说新闻啊,杂七杂八的,我们暂时把他当作银行卡包用

从而得知,我们需要做一个银行卡包,那么它里面都有些啥内容呢?
        卡包最主要的就是银行卡啊,那么钱包的内容是啥呢?   ok !    钱包的内容就是一个区块地址

三、钱包地址

问:钱包地址是啥呢?

答:“钱包地址是一串16位进制的字符串”

        “我都没接触过,区块是啥我都不清楚,我怎么做啊!“

        “这东西肯定很难,又是什么16进制,什么的,肯定还有很多算法,算了不看了”

..............................................?

           好的,其实很简单,你想想,区块这东西听着很深奥,那么是不是已经有大佬帮我们开路了呢?然后java语言的生态在全世界来说是不是很广说白了就是调包调用API),肯定有现成的包给你用的。

四、具体实现

问:好的,那我们用java怎么去做。

答:看下面

首先我们得引用几个包

第一个:tron 也就是 trx需要用的核心包

GitHub:tron.tronprotocol

//org.tron.cli 包 在git上可以下得到,所以在本地引用即可

<dependency>     <groupId>org.tron.cli</groupId>     <artifactId>core</artifactId>     <version>4.7.0</version>     <scope>system</scope>     <systemPath>${project.basedir}/src/main/java/lib/wallet-cli.jar</systemPath> </dependency> 

第二个:web3J 主网包 ETH

//宝宝我用的是5.0.0 方法更全面,对比之前的4.8   4.0这些去掉了很多方法,然而优化了很多地方,具体可以去看看

<dependency>     <groupId>org.web3j</groupId>     <artifactId>core</artifactId>     <version>5.0.0</version> </dependency>

第三个:bitcoinj 主网包 就是BTC的工具包

//我这里用的是0.14.7 这个包里面方法很全面,阅读源码看起来也很清晰。而且推荐使用的也是这个

<dependency>     <groupId>org.bitcoinj</groupId>     <artifactId>bitcoinj-core</artifactId>     <version>0.14.7</version>     <exclusions>         <exclusion>             <groupId>com.google.guava</groupId>             <artifactId>guava</artifactId>         </exclusion>     </exclusions> </dependency> 

好的以上就是具体需要用到的核心包,接下来看代码实现

1.具体代码实现

1.1公共方法

        下面是一些算法,就是16进制转字符串啊,这些东西,我们在生成钱包后返回的是一个10进制byte[]数组,所以我们需要转换成相应16进制的字符串,

PS:下面代码复制过去没用,你需要去下载我的完整项目才行,最下面的GIT地址

   /**      * 十六进制字符串转换为字节数组      * @param s 16进制的字符串,我们的私钥就是一个16进制的字符串      * @return byte[]      */     public static byte[] hexStringToByteArray(String s) {         int len = s.length();         byte[] data = new byte[len / 2];         for (int i = 0; i < len; i += 2) {             data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)                     + Character.digit(s.charAt(i + 1), 16));         }         return data;     }      /**      * 创建一个指定长度的 byte[]      * @param length 长度      * @return byte[]      */     public static byte[] generateRandomBytes(int length) {         byte[] bytes = new byte[length];         new SecureRandom().nextBytes(bytes);         return bytes;     }      /**      * byte[]数组转换成十六进制字符串,我们私钥刚创建出来是一个byte数组,      * 然后需要转换成16进制字符串才能正常使用      * @param bytes bytes      * @return String      */     public static String bytesToHex(byte[] bytes) {         StringBuilder hexString = new StringBuilder();         for (byte b : bytes) {             String hex = Integer.toHexString(0xff & b);             if (hex.length() == 1) {                 hexString.append('0');             }             hexString.append(hex);         }         return hexString.toString();     } 
1.2常量

        首先我们还是要有一些概念的,BIP44_ZERO_PATH  是啥,他是一个路径(看注释)

        PS:常量解释看注释

    /**      * 主网路径  m44'/60'/0'/0/0 主流钱包一般用的都是这个      * ps:其余的钱包可能有自定义路径或者是  m44'/60'/0'/0      *    我们已主网路径为例子      */     public static final ImmutableList<ChildNumber> BIP44_ZERO_PATH = ImmutableList.of(new ChildNumber(44, true), new ChildNumber(60, true),             ChildNumber.ZERO_HARDENED, ChildNumber.ZERO, ChildNumber.ZERO);      public static final String TRX = "TRX";     public static final String ETH = "ETH";     public static final String BTC = "BTC";      /**      * 默认密码(创建钱包的时候用)      */     public static final String PASSWORD = "123456";      /**      * keyStore 文件路径;      * ps:keyStore 是钱包中的一个重要节点,备份可以使用(当然助记词也可以)      */     public static final String KEYSTORE_PATH = System.getProperty("user.dir")+"/keyStore";
1.3trx相关方法
/**      * 创建TRX钱包      * 这个没有keysTRON      * 不过可以试一下熵值创建,然后吧这些信息保存起来      * key,address等信息存起来自己定义一个keyStrone      * @return module      */     public WalletModule createWallet(){         WalletModule module = new WalletModule();         byte[] entropy = WalletInitMethod.generateRandomBytes(16);//其实这个你就可以保存起来,因为是生成助记词很重要的一个熵,没办法逆推算,写入到keyStron种         String mnemonic = MnemonicUtils.generateMnemonic(entropy);         byte[] seed = MnemonicUtils.generateSeed(mnemonic, "");         // 从种子生成私钥         ECKey ecKey = ECKey.fromPrivate(seed);          // 获取公钥和地址         byte[] publicKeyBytes = ecKey.getPubKey();         String address = Base58.encode(ecKey.getAddress());         module.setAddress(address);         module.setPublicKey(WalletInitMethod.bytesToHex(publicKeyBytes));         module.setPrivateKey(WalletInitMethod.bytesToHex(ecKey.getPrivateKey()));         module.setMnemonic(Arrays.asList(mnemonic.split(" ")));         return module;     }      /**      * 其实就是省了创建助记词的步骤,      * @param mnemonic 助记词,A B C D 这种隔空格二的形式      * @return      */     public WalletModule createWalletByMnemonic(String mnemonic){         WalletModule module = new WalletModule();         byte[] seed = MnemonicUtils.generateSeed(mnemonic, "");         // 从种子生成私钥         ECKey ecKey = ECKey.fromPrivate(seed);          // 获取公钥和地址         byte[] publicKeyBytes = ecKey.getPubKey();         String address = Base58.encode(ecKey.getAddress());         module.setAddress(address);         module.setPublicKey(WalletInitMethod.bytesToHex(publicKeyBytes));         module.setPrivateKey(WalletInitMethod.bytesToHex(ecKey.getPrivateKey()));         module.setMnemonic(Arrays.asList(mnemonic.split(" ")));         return module;     }      /**      * 根据私钥生成钱包,因为没有原始熵的原因,所以就没有生成助记词      * @param privateKey 私钥 16进制的      * @return WalletModule      */     public WalletModule createWalletByPrivateKey(String privateKey){         WalletModule module = new WalletModule();          // 将私钥转换为字节数组         byte[] privateKeyBytes = WalletInitMethod.hexStringToByteArray(privateKey);         // 使用私钥生成 ECKey 对象         ECKey ecKey = ECKey.fromPrivate(privateKeyBytes);          // 获取公钥和地址         byte[] publicKeyBytes = ecKey.getPubKey();         String address = Base58.encode(ecKey.getAddress());          module.setAddress(address);         module.setPublicKey(WalletInitMethod.bytesToHex(publicKeyBytes));         module.setPrivateKey(WalletInitMethod.bytesToHex(ecKey.getPrivateKey()));         return module;     } 
1.4eth相关方法
    /**      * 生成一个ETH钱包(主网)      * 包含生成keyStore      *      * @return WalletModule      * @throws CipherException e      * @throws IOException     e      */     public WalletModule createWallet() throws CipherException, IOException {         WalletModule module = new WalletModule();         Bip39Wallet walletEthereum = WalletInitMethod.createWalletEthereum();         String mnemonic = walletEthereum.getMnemonic();         Credentials credentials = WalletUtils.loadBip39Credentials(Constants.PASSWORD, mnemonic);         ECKeyPair ecKeyPair = credentials.getEcKeyPair();         module.setMnemonic(Arrays.asList(walletEthereum.getMnemonic().split(",")));         module.setKeyStoreFileName(walletEthereum.getFilename());         module.setPublicKey(ecKeyPair.getPublicKey().toString(16));         module.setPrivateKey(ecKeyPair.getPrivateKey().toString(16));         module.setAddress(credentials.getAddress());         return module;     }      /**      * 这里传 A B C D这样的助记词,懒得做验证再处理了      * 当然这里没有keyStore      *      * @param mnemonic 助记词      * @return WalletModule      */     public static WalletModule createWalletByMnemonic(String mnemonic) {         WalletModule module = new WalletModule();         Credentials credentials = WalletUtils.loadBip39Credentials(Constants.PASSWORD, mnemonic);         ECKeyPair ecKeyPair = credentials.getEcKeyPair();         module.setPublicKey(ecKeyPair.getPublicKey().toString(16));         module.setPrivateKey(ecKeyPair.getPrivateKey().toString(16));         module.setAddress(credentials.getAddress());         return module;     }      /**      * 根据私钥生成一个ETH钱包      *      * @param privateKey 私钥(16进制的私钥哦)      * @return WalletModule      */     public static WalletModule createWalletByPrivateKey(String privateKey) {         WalletModule module = new WalletModule();         Credentials credentials = Credentials.create(privateKey);         ECKeyPair ecKeyPair = credentials.getEcKeyPair();         module.setPublicKey(ecKeyPair.getPublicKey().toString(16));         module.setPrivateKey(ecKeyPair.getPrivateKey().toString(16));         module.setAddress(credentials.getAddress());         return module;     }      /**      * 根绝keyStore 生成一个钱包      *      * @param password  这个注意,密码一定得正确 要不然就是 Invalid password provided      * @param file_Path keyStore 文件路径      * @return WalletModule      * @throws CipherException e      * @throws IOException     e      */     public static WalletModule createWalletByKeyStore(String password, String file_Path) throws CipherException, IOException {         WalletModule module = new WalletModule();         //用loadCredentials 方法就行         Credentials credentials = WalletUtils.loadCredentials(password, file_Path);         ECKeyPair ecKeyPair = credentials.getEcKeyPair();         module.setPublicKey(ecKeyPair.getPublicKey().toString(16));         module.setPrivateKey(ecKeyPair.getPrivateKey().toString(16));         module.setAddress(credentials.getAddress());         return module;     }  
1.5btc相关方法
    /**      * 创建BTC钱包      * @return WalletModule      */     public WalletModule createWallet(){         WalletModule module = new WalletModule();         try {             List<String> list = WalletInitMethod.createMnemonic();             byte[] seed = MnemonicCode.INSTANCE.toEntropy(list);             DeterministicSeed deterministicSeed = new DeterministicSeed(list,seed,null,new Date().getTime());             Wallet wallet = Wallet.fromSeed(NetworkParameters.fromID("org.bitcoin.production"), deterministicSeed);//主网,你也可以选择测试网             module.setAddress(wallet.currentReceiveAddress().toString());             wallet.getIssuedReceiveKeys();             //ps:这里为什么要做一个这样的处理,是因为BitcoinJ 库会从比特币网络中下载区块并同步交易历史,             // 这个过程可能需要一些时间,特别是在刚开始使用钱包时,或者你可以添加一个监听器addChangeEventListener 也行             while (wallet.getIssuedReceiveKeys().isEmpty()){                 Thread.sleep(2000);//直接等待五秒             }             ECKey ecKey  = wallet.getIssuedReceiveKeys().get(0);             module.setMnemonic(list);             module.setPrivateKey(ecKey.getPrivateKeyAsHex());             module.setPublicKey(ecKey.getPublicKeyAsHex());         } catch (MnemonicException.MnemonicWordException | MnemonicException.MnemonicChecksumException |                  MnemonicException.MnemonicLengthException | InterruptedException e) {             throw new RuntimeException(e);         }         return module;     }      /**      * 这个就是把助记词传过来就行      * @param mnemonic mnemonic      * @return WalletModule      */     public WalletModule createWalletByMnemonic(List<String> mnemonic){         WalletModule module = new WalletModule();         try {             List<String> list = mnemonic;             byte[] seed = MnemonicCode.INSTANCE.toEntropy(list);             DeterministicSeed deterministicSeed = new DeterministicSeed(list,seed,null,new Date().getTime());             Wallet wallet = Wallet.fromSeed(NetworkParameters.fromID("org.bitcoin.production"), deterministicSeed);//主网,你也可以选择测试网             module.setAddress(wallet.currentReceiveAddress().toString());             wallet.getIssuedReceiveKeys();             //ps:这里为什么要做一个这样的处理,是因为BitcoinJ 库会从比特币网络中下载区块并同步交易历史,             // 这个过程可能需要一些时间,特别是在刚开始使用钱包时,或者你可以添加一个监听器addChangeEventListener 也行             while (wallet.getIssuedReceiveKeys().isEmpty()){                 Thread.sleep(2000);//直接等待五秒             }             ECKey ecKey  = wallet.getIssuedReceiveKeys().get(0);             module.setMnemonic(list);             module.setPrivateKey(ecKey.getPrivateKeyAsHex());             module.setPublicKey(ecKey.getPublicKeyAsHex());         } catch (MnemonicException.MnemonicWordException | MnemonicException.MnemonicChecksumException |                  MnemonicException.MnemonicLengthException | InterruptedException e) {             throw new RuntimeException(e);         }         return module;     }        /**      * 根据私钥生成助记地址      * @param privateKey privateKey      * @return WalletModule      */     public WalletModule createWalletByPrivate(String privateKey){         WalletModule module = new WalletModule();         byte[] bytes = hexStringToByteArray(privateKey);         ECKey ecKey = ECKey.fromPrivate(bytes);         MainNetParams mainNetParams = MainNetParams.get();         String address = ecKey.toAddress(mainNetParams).toString();         module.setAddress(address);         module.setPrivateKey(ecKey.getPrivateKeyAsHex());         module.setPublicKey(ecKey.getPublicKeyAsHex());         return module;     }  

五.实现的结果

这是生成的keyStron:

{   "address": "ab2d749ae5ceb1de1dfc41a7b875627982b8fcef",   "id": "473b287f-fe5a-41e4-aa97-4a91b76156dc",   "version": 3,   "crypto": {     "cipher": "aes-128-ctr",     "ciphertext": "30e30fb4584ab5f85b105e7b5a5d60f45ecedbe347e768d09de8bb75c0018be5",     "cipherparams": {       "iv": "ebc6f4d1d84886c39ed3b89be4774580"     },     "kdf": "scrypt",     "kdfparams": {       "dklen": 32,       "n": 4096,       "p": 6,       "r": 8,       "salt": "72177e219fabf5555ac21f989fc9e25e10b4a2136d9498443970efdd8e69b176"     },     "mac": "e58af76dac43694732ab53905c2d8e9b0b8760d23f4921ccd55d287f67130f1c"   } }

PS:本来想写一个test类的,但是我太懒了,所以用main方法代替了,对了源码我放在git上了,你们需要的就去下载,打包就能用,

6重要信息!!

不过你们去下载的要给我点击Star啊! 要不然我做鬼都托梦来骂你!

我的git地址

GitHub - lxxGOd/BTC-ETH-TRX-

最后:我哥哥镇楼

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!