Generieren Sie Bitcoin-Adressen mit Java in sechs Schritten

In diesem Artikel werde ich erklären, wie ein Java-Programm zum Generieren der P2PKH-Bitcoin-Adresse (Pay to Public Key Hash) (komprimierter und unkomprimierter öffentlicher Schlüssel) geschrieben wird. Dies sind drei Artikel-Tutorials, in denen gezeigt wird, wie mithilfe der Java-Programmierung unterschiedliche Bitcoin-Adressen generiert werden.

Bitcoin-Adressen sind 26 bis 35 Zeichen lang und bestehen aus alphabetischen und numerischen Zeichen. Sie beginnen entweder mit „1“, „3“ oder „bc1“.

Derzeit werden drei Bitcoin-Adressformate verwendet:

1. P2PKH (Pay to Public Key Hash) (Adresse beginnt mit der Nummer „1“)

Beispiel: 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2

2. P2SH (Pay an Script Hash) (Adresse beginnt mit der Nummer „3“)

Beispiel: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy

3. Bech32 (Adresse beginnt mit “bc1”)

Beispiel: bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq

Die Bitcoin-Adresse ist eine zufällige Zeichenfolge im BASE58-Codierungsformat, die zum Senden und Empfangen von Bitcoins im Bitcoin-Netzwerk verwendet wird. Es handelt sich um eine öffentlich-private Asymmetrie-Schlüssel-Kryptographie, die auf ECDSA basiert. Der öffentliche Teil des Schlüssels wird zum Generieren einer Bitcoin-Adresse verwendet. Der entsprechende private Schlüssel wird verwendet, um die Bitcoin-Transaktion als Bestätigung und Nachweis zum Zeitpunkt der Transaktion zu signieren.

Technisch gesehen stammt die Bitcoin-Adresse von ECDSA. Wird vom öffentlichen Teil des Schlüssels generiert und verwendet SHA-256 und RIPEMD-160 Hash, wie unten beschrieben, um den resultierenden Hash zu verarbeiten und schließlich Base58 zu verwenden. Der Schlüssel wird durch den Prüfcode codiert.

Sehen wir uns an, wie Sie JCE (Java-Verschlüsselungserweiterung), Bouncy Castle (RIPEMD-160) und schließlich Base58-Codierung in der “Bitcoinj” -Bibliothek verwenden, um die Bitcoin-Adresse zu generieren.

Schritt 1: Initialisieren Sie den Sicherheitsdienstanbieter.

Wir haben den BouncyCastleProvider als Sicherheitsanbieter hinzugefügt, da wir Klassen davon verwenden werden.

java.security.Security.addProvider (neuer BouncyCastleProvider ());

Schritt 2: Generieren Sie ein ECDSA-Schlüsselpaar

Wir haben crypto-3.3.1.jar verwendet, das von web3j entwickelt wurde. Sie können es von https://jar-download.com/artifacts/org.web3j/crypto/3.3.1/source-code

herunterladen

BigInteger privKey = Keys.createEcKeyPair (). getPrivateKey ();

AUSGABE: Privater Schlüssel: a76448f06981aeb02df458f657be1f2994729f8df0de672ecc0095421089f5bc

Der generierte private Schlüssel wird normalerweise in digitalen Geldbörsen gespeichert.

BigInteger pubKey = Sign.publicKeyFromPrivate (privKey);

ECKeyPair keyPair = neues ECKeyPair (privKey, pubKey);

AUSGABE: Öffentlicher Schlüssel: f51b58c89eebcdcdedfb6733bfe45fb884186e8277910ea7dea83fd44380a96de8671ddb36f0bf38d502d9ec7b1973ffe6d696431edc163d73f95cf9acd21

Der öffentliche Teil des oben generierten Schlüssels wird in eine Bitcoin-Adresse codiert. Der öffentliche ECDSA-Schlüssel wird durch einen Punkt auf einer elliptischen Kurve dargestellt. Die X- und Y-Koordinaten dieses Punktes umfassen den öffentlichen Schlüssel.

Sobald wir mit der ECDSA-Schlüsselgenerierung fertig sind, müssen wir nur noch die Bytes 0x04 am Anfang unseres öffentlichen Schlüssels hinzufügen. Das Ergebnis ist ein vollständiger öffentlicher Bitcoin-Schlüssel.

Aber wir können es besser machen, da wir den Schlüssel wie unten gezeigt komprimieren können. Dieser Schlüssel enthält dieselben Informationen, ist jedoch fast doppelt so kurz wie der unkomprimierte Schlüssel.

String bcPub = compressPubKey (pubKey);

AUSGABE: Komprimierter öffentlicher Schlüssel: 02f51b58c89eebcdcdedfb6733bfe45fb884186e8277910ea7dea83fd44380a96d

Schritt 3: Generieren Sie Hashes basierend auf dem öffentlichen Schlüssel

Hier müssen wir SHA-256 auf den öffentlichen Schlüssel und dann RIPEMD-160 auf das Ergebnis anwenden. Die Reihenfolge ist wichtig.

MessageDigest sha = MessageDigest.getInstance (“SHA-256”);

Byte [] s1 = sha.digest (hexStringToByteArray (bcPub));

AUSGABE: SHA256: b21494d6b893fd73448a5fd7123938c3d5d4ff28d599bbf51eb89ad535e2fd1c

MessageDigest rmd = MessageDigest.getInstance (“RipeMD160”);

Byte [] r1 = rmd.digest (s1);

AUSGABE: RIPEMD160: 0582ab02f0abb93a049ba65e8738d4edec06075a

Schritt 4: Hinzufügen der Adresse des Netzwerktyps zur Ausgabe von Hashing

Versionsbyte vor RIPEMD-160-Hash hinzufügen (0x00 für Hauptnetzwerk). Das Versionsbyte wird verwendet, um zwischen MainNet- und TestNet-Adressen sowie zwischen P2PKH- und P2SH-Adressen zu unterscheiden. Es ist 0x00 für Mainnet und 0x6f für Testnet.

Byte [] r2 = neues Byte [r1.Länge + 1];

r2 [0] = 0;

für (int i = 0; i & lt; r1.length; i ++) {

r2 [i + 1] = r1 [i];

}

AUSGABE: Netzwerkbyte hinzugefügt: 000582ab02f0abb93a049ba65e8738d4edec06075a

Schritt 5: Generieren einer Prüfsumme zur Überprüfung der Integrität des Schlüssels

Jetzt müssen wir die Prüfsumme unseres Schlüssels berechnen. Mit der Prüfsumme soll sichergestellt werden, dass die Daten (in unserem Fall der Schlüssel) während der Übertragung nicht beschädigt wurden. Die Brieftaschensoftware sollte die Prüfsumme überprüfen und die Adresse als ungültig markieren, wenn die Prüfsumme nicht übereinstimmt.

Um die Prüfsumme des Schlüssels zu berechnen, müssen wir SHA-256 zweimal anwenden und dann die ersten 4 Bytes des Ergebnisses nehmen.

Byte [] s2 = sha.digest (r2);

AUSGABE: SHA256: db597d4fe6e6ad49c713be33f5e1907ce5839095e311f103b937acb2ac0cec01

Byte [] s3 = sha.digest (s2);

AUSGABE: SHA256: 62a9971acb5e911c3472f924bfbe836173cef62d35c04b92118d69e6b3bf2602

Die ersten 4 Bytes des Ergebnisses des zweiten Hashings werden als Adressprüfsumme verwendet. Es wird an den obigen RIPEMD160-Hash angehängt und generiert eine 25-Byte-Bitcoin-Adresse.

Byte [] a1 = neues Byte [25];

für (int i = 0; i & lt; r2.length; i ++) {

a1 [i] = r2 [i];

}

für (int i = 0; i & lt; 4; i ++) {

a1 [21 + i] = s3 [i];

AUSGABE: Vor der Base58-Codierung: 000582ab02f0abb93a049ba65e8738d4edec06075a62a9971a

Schritt 6: Anwenden der Base58-Codierung

Wir verwenden die Base58.encode () -Methode der “bitcoinj” -Bibliothek, um die endgültige Bitcoin-Adresse zu erhalten.

Base58.encode(a1)

AUSGABE: Nach der Base58-Codierung: 1W8uw3vTUD5CwaprwCWGPoMjk482xWm1K

Herzlichen Glückwunsch, Sie haben Ihre erste Bitcoin-Adresse generiert.

Für die Ausführung des obigen Codes benötigen wir die folgenden Dienstprogrammfunktionen:

Die folgende Funktion wird verwendet, um das Byte zum besseren Verständnis des Benutzers in eine Hex-Darstellung umzuwandeln.

privater statischer String bytesToHex (byte [] hashInBytes) {

StringBuilder sb = neuer StringBuilder ();

für (int i = 0; i & lt; hashInBytes.length; i ++) {

sb.append (Integer.toString ((hashInBytes [i] & amp; 0xff) + 0x100, 16) .substring (1));

}

gibt sb.toString () zurück;

Wie Sie vielleicht wissen, ist der öffentliche Schlüssel ein Punkt (X, Y) auf der elliptischen Kurve. Wir kennen die Kurve und für jedes X gibt es nur zwei Ys, die den Punkt definieren, der auf dieser Kurve liegt. Warum also Y behalten? Behalten wir stattdessen X und das Vorzeichen von Y. Später können wir bei Bedarf daraus Y ableiten. Die Einzelheiten sind wie folgt: Wir nehmen X aus dem öffentlichen ECDSA-Schlüssel. Nun addieren wir 0x02, wenn das letzte Byte von Y gerade ist, und das Byte 0x03, wenn das letzte Byte ungerade ist. Die folgende Methode wird verwendet, um einen komprimierten öffentlichen Schlüssel basierend auf dem angegebenen öffentlichen Schlüssel in BigInteger zu generieren.

öffentlicher statischer String compressPubKey (BigInteger pubKey) {

String pubKeyYPrefix = pubKey.testBit (0)? “03”: “02”;

String pubKeyHex = pubKey.toString (16);

String pubKeyX = pubKeyHex.substring (0, 64);

return pubKeyYPrefix + pubKeyX;

Die hexadezimale Darstellung in einem String und seine Byte-Array-Darstellung unterscheiden sich in Java (“0x98”! = “98”). Der in diesem Programm verwendete Hashing-Algorithmus akzeptiert das Byte-Array. Verwenden Sie daher die folgende Methode, um hexadezimal in ein Byte-Array zu konvertieren:

öffentliches statisches Byte [] hexStringToByteArray (String s) {

Byte [] b = neues Byte [s.length () / 2];

für (int i = 0; i & lt; b.Länge; i ++) {

int index = i * 2;

int v = Integer.parseInt (s.substring (Index, Index + 2), 16);

b [i] = (Byte) v;

}

return b;

Verwenden Sie die folgenden Tools, um das Ergebnis von Zwischenschritten zu überprüfen:

Um zu überprüfen, ob die generierte Adresse gültig ist oder nicht, verwenden Sie: https://awebanalysis.com/de/bitcoin-address-validate/
2. Base58-Kodierungs- und Dekodierungswerkzeug http://lenschulwitz.com/base58
3. Spielen Sie mit dem Bitcoin-Adressgenerator: https://brainwalletx.github.io/#generator

Der obige Artikel wurde aufgrund der folgenden Artikel erstellt:

Referenzen: