Private Brain Key-Generierung und öffentliche Adresse stimmen nicht mit Java überein

Ich versuche, einen öffentlichen und privaten Schlüsselsatz aus einer Eingabezeichenfolge in Java zu generieren. (Ja, mir ist bewusst, dass dies eine gefährliche Praxis sein kann) Ich verwende Bitcoin für eine externe Bibliothek.

Ich habe derzeit:

 //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();

  }

Wenn ich Folgendes ausführe: Seed String: icecreampaintjob

Ich bekomme folgendes:

Öffentlich: 1KdoiXMYFn2qa8uGGiNqfrwFRDu3j2qQNA

Privat: dba1e3e22415c56af772dee422add21b7382ea35f2af77852a8069d02e47ecf4

Mit bitaddress.org zur Kreuzverifizierung bekomme ich:

Privat: 5KV1o7tRK8pNqrPNYyi38nrik9r2Y85sjdgFDttnDiT1uZrQ1fj (MACHT NICHT)

Öffentlich: 1KdoiXMYFn2qa8uGGiNqfrwFRDu3j2qQNA (STIMME ZU)

Was vermisse ich?

Antworten (2)

Wie bitaddress.org BrainWallet in seiner Anzeige sagt

Private Key (Wallet Import Format): 
5KV1o7tRK8pNqrPNYyi38nrik9r2Y85sjdgFDttnDiT1uZrQ1fj 

Das Wallet-Importformat ist die übliche base58-Panzerung, die auf den Privatekey-Wert mit „Version“ 0x80 angewendet wird.
Siehe https://en.bitcoin.it/wiki/Wallet_import_format oder ausführlicher https://en.bitcoin.it/wiki/Base58Check_encoding . Dies ist im Grunde ein Duplikat von Gibt es eine Möglichkeit, eine Brain Wallet über die Befehlszeile oder Konsole zu generieren? obwohl das bash + dc anstelle von Java verwendet.

Nicht getestet, aber für mich VersionChecksummedBytes(0x80,bytes).toBase58()sieht es so aus.

Wo ist VersionChecksumdBytes? Ist die Methode Teil der bitcoinj-Bibliothek?
@JohnDown ja, es ist in Bitcoinj. Es ist eine Klasse (in Java beginnen Klassennamen konventionell mit Großbuchstaben und Methodennamen mit Kleinbuchstaben) und ist die Oberklasse der AddressKlasse, die Ihr Code bereits verwendet - so habe ich es gefunden.
Können Sie das näher erläutern? Die Methode ist geschützt und ich kann von meiner Hauptklasse aus nicht darauf zugreifen. Im Moment habe ich: Address output = new VersionChecksummedBytes(0x80,privateKeyByte).toBase58();
Siehe Java-Dokumentation: bitcoinj.github.io/javadoc/0.12.3/…
In dem Code (wo ich nachgesehen habe) ist der Ctor tatsächlich geschützt (und ich habe es nicht bemerkt), aber die Methode ist öffentlich. (1) Es ist Open Source, also könnten Sie es ändern. (2) Es ist Java, also könnten Sie mit Reflektion überschreiben. (3) Aber der sauberste Weg ist, einfach eine sehr einfache Unterklasse zu erstellen und diese zu verwenden. Und (4) wenn Sie dies tun, ist das Ergebnis von toBase58(oder toStringdas es einfach umschließt) String.

Ich denke, new VersionedChecksummedBytes(0x80, priv).toBase58()das ist die richtige Idee, aber die Konstruktoren sind geschützt und ich kann keine statische Factory-Funktion finden. Mit der getPrivateKeyEncodedMethode von ECKeykönnen wir jedoch ein DumpedPrivateKeyObjekt erhalten, das von abgeleitet ist VersionedChecksummedBytes. Wir können auch die getPrivateKeyAsWiFMethode verwenden, ECKeydie direkter ist. Oder wir können Dinge manuell tun:

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

  }
}

0x01Beachten Sie, dass Sie, wenn Sie die gleiche manuelle Berechnung für einen komprimierten Schlüssel durchführen möchten, ein zusätzliches Byte nach dem 32-Byte-Geheimnis und direkt vor der Prüfsumme hinzufügen müssen . Wenn Sie dasselbe für ein Testnetzwerk tun möchten, ersetzen Sie das vordere Versionsbyte 0x80durch 0xef.