私有大腦密鑰生成和公共地址不匹配 Java
我正在嘗試從 Java 中的輸入字元串生成公鑰和私鑰集。(是的,我知道這可能是一種危險的做法)我將 bitcoinj 用於外部庫。
我目前有:
//public key generation from private key static String getPublicKey(byte[] privKey) { Address address = new Address(MainNetParams.get(), Utils.sha256hash160(ECKey.fromPrivate(privKey, false).getPubKey())); return address.toString(); } ///hash string to generate private key from string static byte[] sha256(String base) { try{ MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(base.getBytes("UTF-8")); return hash; } catch(Exception ex){ throw new RuntimeException(ex); } } //encode private key as string to display static String privToString(byte[] hash) { StringBuffer hexString = new StringBuffer(); for (int i = 0; i < hash.length; i++) { String hex = Integer.toHexString(0xff & hash[i]); if(hex.length() == 1) hexString.append('0'); hexString.append(hex); } return hexString.toString(); }
當我執行以下命令時:種子字元串:icecreampaintjob
我得到以下資訊:
公共:1KdoiXMYFn2qa8uGGiNqfrwFRDu3j2qQNA
私人:dba1e3e22415c56af772dee422add21b7382ea35f2af77852a8069d02e47ecf4
使用 bitaddress.org 交叉驗證我得到:
私人:5KV1o7tRK8pNqrPNYyi38nrik9r2Y85sjdgFDttnDiT1uZrQ1fj(沒有 MACTH)
公開:1KdoiXMYFn2qa8uGGiNqfrwFRDu3j2qQNA(比賽)
我錯過了什麼?
正如 bitaddress.org BrainWallet 在其顯示中所說
Private Key (Wallet Import Format): 5KV1o7tRK8pNqrPNYyi38nrik9r2Y85sjdgFDttnDiT1uZrQ1fj
錢包導入格式是應用於“版本”0x80 的私鑰值的常用 base58 保護。
請參閱<https://en.bitcoin.it/wiki/Wallet_import_format>或更詳細的<https://en.bitcoin.it/wiki/Base58Check_encoding>。這基本上是重複Is there a way to generate a brain wallet from the command line or console? 儘管它使用 bash+dc 而不是 Java。
未經測試,但在我看來
VersionChecksummedBytes(0x80,bytes).toBase58()
是這樣的。
我認為
new VersionedChecksummedBytes(0x80, priv).toBase58()
是正確的想法,但是建構子受到保護,我找不到靜態工廠函式。但是,使用 的getPrivateKeyEncoded
方法ECKey
,我們可以獲得一個DumpedPrivateKey
派生自 的對象VersionedChecksummedBytes
。我們也可以使用更直接的getPrivateKeyAsWiF
方法。ECKey
或者我們可以手動操作:import java.math.BigInteger; import org.bitcoinj.core.VersionedChecksummedBytes; import org.bitcoinj.core.ECKey; import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Base58; import org.bitcoinj.params.MainNetParams; public class Test { public static void main(String args[]){ NetworkParameters mainNet = MainNetParams.get(); String hex = "dba1e3e22415c56af772dee422add21b7382ea35f2af77852a8069d02e47ecf4"; BigInteger big = new BigInteger(hex, 16); ECKey key = ECKey.fromPrivate(big, false); // uncompressed byte[] priv = key.getPrivKeyBytes(); String wif1 = key.getPrivateKeyEncoded(mainNet).toBase58(); System.out.println(wif1); // 5KV1o7tRK8pNqrPNYyi38nrik9r2Y85sjdgFDttnDiT1uZrQ1fj String wif2 = key.getPrivateKeyAsWiF(mainNet); System.out.println(wif2); // 5KV1o7tRK8pNqrPNYyi38nrik9r2Y85sjdgFDttnDiT1uZrQ1fj byte[] bytes = new byte[1 + 32 + 4]; bytes[0] = (byte) 0x80; System.arraycopy(priv, 0, bytes, 1, 32); byte[] checksum = Sha256Hash.hashTwice(bytes, 0, 33); System.arraycopy(checksum, 0, bytes, 33, 4); String wif3 = Base58.encode(bytes); System.out.println(wif3); // 5KV1o7tRK8pNqrPNYyi38nrik9r2Y85sjdgFDttnDiT1uZrQ1fj } }
請注意,如果您打算對壓縮密鑰進行相同的手動計算,則需要
0x01
在 32 字節密鑰之後和校驗和之前添加一個額外的字節。如果您想對測試網路做同樣的事情,請將前面的版本字節替換0x80
為0xef
.