一、前言
#最近閑著沒(méi)事做,然后看聽(tīng)到說(shuō)什么BTC瘋漲,這類的小道消息。
?????????哦豁~,這一下就讓我覺(jué)得非常好奇,說(shuō),他們這些東西是怎樣在鏈上存在的呢,然后他們那個(gè)一串串的地址又是啥,imtoken錢(qián)包又是怎么實(shí)現(xiàn)的呢。
????????根據(jù)以上疑問(wèn),我自己去研究,自己去做一個(gè)錢(qián)包可以不?PS:主要是這個(gè)問(wèn)題簡(jiǎn)單點(diǎn),那些什么在鏈上存在的我沒(méi)研究透。
好的鳴人不說(shuō)暗話,我們開(kāi)始!
? ? ? ??
二、理解區(qū)塊錢(qián)包
????????首先我們得知道傳說(shuō)中的imtoken,web3等錢(qián)包是什么東西,它實(shí)際上就是一個(gè)以地址為核心的一個(gè)軟件
ps:當(dāng)然現(xiàn)在他們也有很多其他的功能,比如說(shuō)新聞啊,雜七雜八的,我們暫時(shí)把他當(dāng)作銀行卡包用
從而得知,我們需要做一個(gè)銀行卡包,那么它里面都有些啥內(nèi)容呢?
? ? ? ? 卡包最主要的就是銀行卡啊,那么錢(qián)包的內(nèi)容是啥呢?? ?ok !? ? 錢(qián)包的內(nèi)容就是一個(gè)區(qū)塊地址
三、錢(qián)包地址
問(wèn):錢(qián)包地址是啥呢?
答:“錢(qián)包地址是一串16位進(jìn)制的字符串”
? ? ? ? “我都沒(méi)接觸過(guò),區(qū)塊是啥我都不清楚,我怎么做??!“
? ? ? ? “這東西肯定很難,又是什么16進(jìn)制,什么的,肯定還有很多算法,算了不看了”
..............................................?
? ? ? ? ? ?好的,其實(shí)很簡(jiǎn)單,你想想,區(qū)塊這東西聽(tīng)著很深?yuàn)W,那么是不是已經(jīng)有大佬幫我們開(kāi)路了呢?然后java語(yǔ)言的生態(tài)在全世界來(lái)說(shuō)是不是很廣(說(shuō)白了就是調(diào)包調(diào)用API),肯定有現(xiàn)成的包給你用的。
四、具體實(shí)現(xiàn)
問(wèn):好的,那我們用java怎么去做。
答:看下面
首先我們得引用幾個(gè)包
第一個(gè):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>
第二個(gè):web3J 主網(wǎng)包 ETH
//寶寶我用的是5.0.0 方法更全面,對(duì)比之前的4.8? ?4.0這些去掉了很多方法,然而優(yōu)化了很多地方,具體可以去看看
<dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>5.0.0</version> </dependency>
第三個(gè):bitcoinj 主網(wǎng)包 就是BTC的工具包
//我這里用的是0.14.7 這個(gè)包里面方法很全面,閱讀源碼看起來(lái)也很清晰。而且推薦使用的也是這個(gè)
<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>
好的以上就是具體需要用到的核心包,接下來(lái)看代碼實(shí)現(xiàn)
1.具體代碼實(shí)現(xiàn)
1.1公共方法
? ? ? ? 下面是一些算法,就是16進(jìn)制轉(zhuǎn)字符串啊,這些東西,我們?cè)谏慑X(qián)包后返回的是一個(gè)10進(jìn)制byte[]數(shù)組,所以我們需要轉(zhuǎn)換成相應(yīng)16進(jìn)制的字符串,
PS:下面代碼復(fù)制過(guò)去沒(méi)用,你需要去下載我的完整項(xiàng)目才行,最下面的GIT地址
/**
* 十六進(jìn)制字符串轉(zhuǎn)換為字節(jié)數(shù)組
* @param s 16進(jìn)制的字符串,我們的私鑰就是一個(gè)16進(jìn)制的字符串
* @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;
}
/**
* 創(chuàng)建一個(gè)指定長(zhǎng)度的 byte[]
* @param length 長(zhǎng)度
* @return byte[]
*/
public static byte[] generateRandomBytes(int length) {
byte[] bytes = new byte[length];
new SecureRandom().nextBytes(bytes);
return bytes;
}
/**
* byte[]數(shù)組轉(zhuǎn)換成十六進(jìn)制字符串,我們私鑰剛創(chuàng)建出來(lái)是一個(gè)byte數(shù)組,
* 然后需要轉(zhuǎn)換成16進(jìn)制字符串才能正常使用
* @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? 是啥,他是一個(gè)路徑(看注釋)
????????PS:常量解釋看注釋
/**
* 主網(wǎng)路徑 m44'/60'/0'/0/0 主流錢(qián)包一般用的都是這個(gè)
* ps:其余的錢(qián)包可能有自定義路徑或者是 m44'/60'/0'/0
* 我們已主網(wǎng)路徑為例子
*/
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";
/**
* 默認(rèn)密碼(創(chuàng)建錢(qián)包的時(shí)候用)
*/
public static final String PASSWORD = "123456";
/**
* keyStore 文件路徑;
* ps:keyStore 是錢(qián)包中的一個(gè)重要節(jié)點(diǎn),備份可以使用(當(dāng)然助記詞也可以)
*/
public static final String KEYSTORE_PATH = System.getProperty("user.dir")+"/keyStore";
1.3trx相關(guān)方法
/**
* 創(chuàng)建TRX錢(qián)包
* 這個(gè)沒(méi)有keysTRON
* 不過(guò)可以試一下熵值創(chuàng)建,然后吧這些信息保存起來(lái)
* key,address等信息存起來(lái)自己定義一個(gè)keyStrone
* @return module
*/
public WalletModule createWallet(){
WalletModule module = new WalletModule();
byte[] entropy = WalletInitMethod.generateRandomBytes(16);//其實(shí)這個(gè)你就可以保存起來(lái),因?yàn)槭巧芍浽~很重要的一個(gè)熵,沒(méi)辦法逆推算,寫(xiě)入到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;
}
/**
* 其實(shí)就是省了創(chuàng)建助記詞的步驟,
* @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;
}
/**
* 根據(jù)私鑰生成錢(qián)包,因?yàn)闆](méi)有原始熵的原因,所以就沒(méi)有生成助記詞
* @param privateKey 私鑰 16進(jìn)制的
* @return WalletModule
*/
public WalletModule createWalletByPrivateKey(String privateKey){
WalletModule module = new WalletModule();
// 將私鑰轉(zhuǎn)換為字節(jié)數(shù)組
byte[] privateKeyBytes = WalletInitMethod.hexStringToByteArray(privateKey);
// 使用私鑰生成 ECKey 對(duì)象
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相關(guān)方法
/**
* 生成一個(gè)ETH錢(qián)包(主網(wǎng))
* 包含生成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這樣的助記詞,懶得做驗(yàn)證再處理了
* 當(dāng)然這里沒(méi)有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;
}
/**
* 根據(jù)私鑰生成一個(gè)ETH錢(qián)包
*
* @param privateKey 私鑰(16進(jìn)制的私鑰哦)
* @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 生成一個(gè)錢(qián)包
*
* @param password 這個(gè)注意,密碼一定得正確 要不然就是 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相關(guān)方法
/**
* 創(chuàng)建BTC錢(qián)包
* @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);//主網(wǎng),你也可以選擇測(cè)試網(wǎng)
module.setAddress(wallet.currentReceiveAddress().toString());
wallet.getIssuedReceiveKeys();
//ps:這里為什么要做一個(gè)這樣的處理,是因?yàn)锽itcoinJ 庫(kù)會(huì)從比特幣網(wǎng)絡(luò)中下載區(qū)塊并同步交易歷史,
// 這個(gè)過(guò)程可能需要一些時(shí)間,特別是在剛開(kāi)始使用錢(qián)包時(shí),或者你可以添加一個(gè)監(jiān)聽(tīng)器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;
}
/**
* 這個(gè)就是把助記詞傳過(guò)來(lái)就行
* @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);//主網(wǎng),你也可以選擇測(cè)試網(wǎng)
module.setAddress(wallet.currentReceiveAddress().toString());
wallet.getIssuedReceiveKeys();
//ps:這里為什么要做一個(gè)這樣的處理,是因?yàn)锽itcoinJ 庫(kù)會(huì)從比特幣網(wǎng)絡(luò)中下載區(qū)塊并同步交易歷史,
// 這個(gè)過(guò)程可能需要一些時(shí)間,特別是在剛開(kāi)始使用錢(qián)包時(shí),或者你可以添加一個(gè)監(jiān)聽(tīng)器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;
}
/**
* 根據(jù)私鑰生成助記地址
* @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;
}
五.實(shí)現(xiàn)的結(jié)果
這是生成的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:本來(lái)想寫(xiě)一個(gè)test類的,但是我太懶了,所以用main方法代替了,對(duì)了源碼我放在git上了,你們需要的就去下載,打包就能用,
6重要信息!!
不過(guò)你們?nèi)ハ螺d的要給我點(diǎn)擊Star啊! 要不然我做鬼都托夢(mèng)來(lái)罵你!
我的git地址
:GitHub - lxxGOd/BTC-ETH-TRX-
最后:我哥哥鎮(zhèn)樓文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-851241.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-851241.html
到了這里,關(guān)于區(qū)塊鏈錢(qián)包“BTC,TRX,ETH”地址生成、助記詞導(dǎo)入、keyStron文件生成等功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!