Wallet

私有大腦密鑰生成和公共地址不匹配 Java

  • August 22, 2016

我正在嘗試從 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 字節密鑰之後和校驗和之前添加一個額外的字節。如果您想對測試網路做同樣的事情,請將前面的版本字節替換0x800xef.

引用自:https://bitcoin.stackexchange.com/questions/43833