Wie werden öffentliche & private Schlüssel in einer Adresse erstellt?

Ich verstehe das allgemeine Konzept. Ich interessiere mich mehr für spezifische Details. Wie wird ein privater Schlüssel generiert. Wie genau wird der öffentliche Schlüssel generiert, wie wird die Adresse aus dem öffentlichen Schlüssel generiert?

Antworten (5)

Der öffentliche und der private Schlüssel in einer Bitcoin-Adresse sind ein normales ECDSA -Schlüsselpaar. Ich habe diesen speziellen Teil von Bitcoins eigenem Code nicht durchforstet, aber die Ablegerprodukte, mit denen ich die Gelegenheit hatte, zu arbeiten, verwenden normalerweise die Kryptobibliothek von Bouncy Castle . Bouncy Castle hat auch eine ausgezeichnete Einführung / Anleitung zur Verwendung ihrer Bibliothek. Ihre Beispiele sind in Java, aber es ist ziemlich einfach und sollte leicht auf andere Sprachen portiert werden.

Es gibt auch eine hervorragende vorgefertigte Bibliothek für die Generierung von JavaScript-Schlüsseln, die von Tom Wu unter der BSD-Lizenz erhältlich ist.

Wie bei der Elliptic-Curve-Verschlüsselung üblich, ist ein privater Schlüssel einfach eine Zufallszahl. Im Fall von secp256k1, der von Bitcoin verwendeten elliptischen Kurve, muss es sich um eine Zahl zwischen 1 und 115792089237316195423570985008687907852837564279074904382605163141518161494336 handeln (oder hexadezimal zwischen 0x1und 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140).

Dieser private Schlüssel wird in einen öffentlichen Schlüssel umgewandelt, indem eine EC-Punkt-Multiplikation mit dem Basispunkt der Kurve durchgeführt wird. Das Ergebnis ist ein (x,y)Koordinatenpaar, das den öffentlichen Schlüssel darstellt.

Schließlich wird RIPEMD160(SHA256(pubkey)), wobei pubkey eine Serialisierung dieser Koordinaten ist, berechnet und zusammen mit einer Prüfsumme in base58 codiert. Dies wird die Adresse.

Wie haben Sie festgestellt, dass dies der maximale Wert ist? Ich möchte sowohl den richtigen als auch den falschen Weg lernen, damit ich von Ihren [Bearbeitungen] lernen kann;)
Ich habe es von en.bitcoin.it/wiki/Secp256k1 kopiert, das es selbst aus dem SEC2-Spezifikationsdokument kopiert hat: secg.org/collateral/sec2_final.pdf
Aktualisierter Link zum SEC2-Dokument secg.org/SEC2-Ver-1.0.pdf
Ist einer dieser beiden Schritte reversibel?
Nein, sind sie nicht (solange ECDLP hart ist).

Private Bitcoin-Schlüssel werden am häufigsten im Wallet-Import-Format (WIF) angezeigt, auch bekannt als base58check (eine in Basis 58 ausgedrückte Zahl mit einer Prüfsumme am Ende und einem Versionsbyte am Anfang).

Um einen privaten WIF-Schlüssel zu erstellen, müssen Sie:

  1. Generieren Sie einen geheimen ECDSA-Exponenten (den privaten Schlüssel) mithilfe der SECP256k1-Kurve.
  2. Konvertieren Sie den geheimen Exponenten/privaten Schlüssel in das base58check-Format.

Hier sind zwei einfache Möglichkeiten, einen geheimen Exponenten zu generieren:

  1. Wählen Sie eine Zufallszahl im Bereich [1, curve_order).
  2. Generieren Sie eine zufällige Hexadezimalzeichenfolge mit 64 Zeichen (die Hexadezimalzeichenfolge einer 256-Bit-Zahl) und überprüfen Sie, ob die Zahl im Bereich [1, curve_order] liegt. Bei Bedarf wiederholen.

Für SECP256k1 ist die Kurvenreihenfolge 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 (oder 1157920892373161954235709850086879078528375642790749043826051831694314L4314L).

Diese Zahl liegt sehr nahe an der größten 256-Bit-Zahl (0xFFF...FFF in Hex), sodass Sie davon ausgehen können, dass Sie die Kurvenreihenfolge niemals überschreiten werden, wenn Sie eine zufällige 256-Bit-Zahl generieren.

Wie Pieter Wuille erwähnte, werden öffentliche Schlüssel durch eine Punktmultiplikation mit dem Basispunkt der Kurve und dem geheimen Exponenten/privaten Schlüssel abgeleitet. Die resultierende (x,y)-Koordinate ist der öffentliche Schlüssel.

Die Bitcoin-Adresse wird ebenso wie der Private Key im base58check-Format angezeigt. Um die Adresse zu erhalten, gehen wir wie folgt vor:

  1. Berechnen Sie den Hash160: reifemd160(sha256(public_key)).
  2. Konvertieren Sie den Hash160 in das base58check-Format.

Um eine Nummer in das base58check-Format zu konvertieren, führen Sie einfach die folgenden Schritte aus:

  1. Konvertieren Sie den Wert in ein Byte-Array und hängen Sie das Versionsbyte an den Anfang an
  2. Berechnen Sie die ersten 4 Bytes von SHA256 (SHA256 (Ergebnis von Schritt 1)) und nennen Sie es die Prüfsumme
  3. Hängen Sie die Prüfsumme an das Ende des Ergebnisses von Schritt 1 an
  4. Verschieben Sie das Ergebnis von Schritt 3 in den Schlüsselraum "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".
  5. Überprüfen Sie, wie viele führende Nullen der ursprüngliche Binärwert hatte, und hängen Sie diese an den Anfang des Ergebnisses von Schritt 4

Hier sind die detaillierteren Anweisungen .

Wenn Sie sich jetzt keine Gedanken über all diese Dinge machen möchten, würde ich mir die Python-Bibliothek Coinkit ( https://github.com/halfmoonlabs/coinkit oder "pip install coinkit") ansehen.

Sie können einfache Operationen wie diese ausführen:

>>> from coinkit.keypair import BitcoinKeypair
>>> hex_private_key = '91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
>>> k = BitcoinKeypair(hex_private_key)
>>> k.private_key()
'91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
>>> k.public_key()
'042c6b7e6da7633c8f226891cc7fa8e5ec84f8eacc792a46786efc869a408d29539a5e6f8de3f71c0014e8ea71691c7b41f45c083a074fef7ab5c321753ba2b3fe'
>>> k.wif_pk()
'5JvBUBPzU42Y7BHD7thTnySXQXMk8XEJGGQGcyBw7CCkw8RAH7m'
>>> k.address()
'13mtgVARiB1HiRyCHnKTi6rEwyje5TYKBW'

Sie können auch zufällige Schlüsselpaare erstellen:

>>> k = BitcoinKeypair()

Und Brain-Wallet-Schlüsselpaare:

>>> passphrase = 'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'
>>> k = BitcoinKeypair().from_passphrase(passphrase)
>>> k.passphrase()
'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'

Offenlegung: Ich bin einer der Schöpfer von Coinkit.

Der Javascript-Code von: http://www.bitaddress.org könnte Ihnen auch ein gutes Beispiel dafür geben.

Wie sie erstellt werden, ist im Wiki vollständig dokumentiert : https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses

Auf Java

  1. Fügen Sie das JAR der bitcoinj -Java-Bibliothek in Ihren Klassenpfad ein
  2. Der Code:

    import com.google.bitcoin.core.*;
    
    NetworkParameters params = new MainNetParams();
    
    String publicAddress = new DumpedPrivateKey(params,
            "KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP").getKey()
            .toAddress(params).toString();
    
  3. Das Ergebnis ist 17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE.

Im JavaScript

Verwenden der bitaddress.org- Javascript-Bibliothek:

var key = new Bitcoin.ECKey('KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP');
console.log(key.getBitcoinAddress());

Das Ergebnis ist 17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE.


Anmerkung 1: Vorher habe ich bitcoin-cli getnewaddressund getan bitcoin-cli dumpprivkey <pubkey>, um das Schlüsselpaar zu erhalten.

Hinweis 2: Um die Dinge noch einfacher zu machen, führen Sie unter Ihrem Verzeichnis https://github.com/pointbiz/bitaddress.org/tree/master/src einfach Folgendes aus:

cat array.map.js cryptojs.js cryptojs.sha256.js cryptojs.pbkdf2.js cryptojs.hmac.js cryptojs.aes.js cryptojs.blockmodes.js cryptojs.ripemd160.js securerandom.js ellipticcurve.js secrets.js biginteger.js qrcode.js bitcoinjs-lib.js bitcoinjs-lib.base58.js bitcoinjs-lib.address.js bitcoinjs-lib.ecdsa.js bitcoinjs-lib.eckey.js bitcoinjs-lib.util.js crypto-scrypt.js > all.js

und Sie erhalten eine 174-KB-Datei, die alles ist, was Sie zum Ausführen benötigen.

Hinweis 3: Wenn Sie diese Datei (von Commit f6c6bbe53df28c1bf51a6216f02ad1467b36c9f7) erhalten möchten, schauen Sie hier: http://pastebin.com/raw.php?i=rH8V2j9H


Das vollständige Funktionsbeispiel

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="http://pastebin.com/raw.php?i=rH8V2j9H"></script>
</head>

<body>
    <form onsubmit="alert(new Bitcoin.ECKey(document.getElementById('pkey').value).getBitcoinAddress());">
        <label>
            Private key:
            <input id="pkey" type="text">
        </label>
    </form>
</body>
</html>