Was ist ein "Derivation Path" und wie funktionieren HD Wallets?

Hier gehts zum Beitrag auf der Webseite:

Alten Beitrag hier ausklappen


Moin zusammen!

In diesem Beitrag solll es rund um das Thema Ableitungspfade gehen und wie eine Wallet es schafft aus unsereren 24 Wörtern praktisch unendlich viele Schlüssel abzuleiten. Mir ist bewusst das dies ein eher unwichtigeres Thema (für den Endnutzer) ist, weshalb ich versucht habe den Beitrag in aufsteigender Schwierigkeit zu schreiben.

Das heisst die ersten Absätze sollten für alle verständlich (und wichtig) sein während es gegen Ende etwas mehr ins Detail geht. Das Thema ist teilweise sehr abstrakt, deswegen scheut euch nicht offene Fragen direkt hier im Thread zu stellen. :)

Los geht’s!

Eine Wallet ist nur ein Schlüssel(bund)

Um wirklich alle abzuholen müssen wir uns zunächst einmal klar machen was eine Wallet konkret überhaupt ist. Hier ein paar Mythen die wir erstmal aus dem Weg räumen müssen bzw. einige Formulierungen die wir konkretisieren:

  • Eine Wallet kontrolliert keine Bitcoin - sondern Schlüssel zu den Bitcoin.

  • Bitcoin liegen nicht auf einer Wallet - sondern Schlüssel liegen auf der Wallet.

  • Eine Mnemonic/Seedphrase ist kein Backup der Bitcoin - sondern ein Backup der Schlüssel zu den Bitcoin.

  • Der Seed, die Schlüssel und sogar Adressen sind nichts anderes als große Zahlen, die in besser lesbaren Zahlensystemen wie z.B. Base58 codiert sind.

Vielleicht denkt man sich: Wo ist denn da der Unterschied?

Ein Ersatzschlüssel eurer Wohnung ist kein Ersatz für eure Wohnung, sondern ein Ersatz für den Zugang zur Wohnung. Anders als bei einer Wohnung müssen wir uns um die Sicherheit der Bitcoin selbst absolut keine Gedanken machen, da diese unveränderlich auf einer dezentralen Datenbank (der Blockchain) gesichert sind.

Deshalb verändert auch eine ein- oder ausgehende Transaktion nichts an den Backups, da die Schlüssel immer noch die selben sind. Egal wie viele Bitcoin wir empfangen oder ausgeben, unser Anfangs erstelltes Backup ist immer noch gültig, da die Schlüssel gleich geblieben sind.

Wieder das Beispiel Wohnung: Wenn wir uns einen neuen Schrank ins Schlafzimmer stellen, bleibt der Haustürschlüssel der gleiche.

Worüber wir uns also Gedanken machen müssen: Die Sicherheit unserer Schlüssel!




Nicht-deterministische Wallets

Heutzutage benutzen die wenigsten von uns noch sogenannte nicht-deterministische Wallets (auch random wallets gennant), da sie in der Benutzung extrem unpraktisch sind. Wir alle kennen das Konzept einer Mnemonic, also den Wiederherstellungswörtern, doch das gibt es bei einer nicht-deterministischen Wallet nicht.

Vereinfacht: Zu jeder Adresse gehört ein öffentlicher Schlüssel, und zu diesem öffentlichen Schlüssel gehört ein privater Schlüssel. Diese Ableitung funktioniert nur in eine Richtung:

Privater Schlüssel → Öffentlicher Schlüssel → Adresse

Die Adresse brauche ich um Bitcoin zu empfangen, den privaten Schlüssel um die Bitcoin auf der Adresse auszugeben und den öffentlichen Schlüssel um zu beweisen dass der private Schlüssel auch wirklich zu dieser Adresse gehört.

Bei einer nicht-deterministischen Wallet stehen alle Schlüsselpaare für sich und haben nichts miteinander zu tun. Das bedeutet: Jeder private Schlüssel muss einzeln abgesichert werden, da ich keinen „Hauptschlüssel“ habe mit dem ich auf alle anderen Schlüssel zurück schließen kann.

Das ist extrem unpraktisch. Erstens, weil es sowieso schon mühsamer ist einen komplexen Schlüssel zu notieren (anstatt einfache englische Wörter) und zweitens, weil ich für jede neue Adresse die ich generiere auch wieder ein neues Backup machen muss. Das kollidiert mit dem gewünschten Anreiz augrund von Privatsphäre immer neue Adressen zu verwenden.

Viele von euch haben so eine Wallet trotzdem schon einmal benutzt, denn eine einfache Paper Wallet ist nichts anderes als eine nicht-deterministische Wallet. Auch die allererste Bitcoin Wallet (in Bitcoin Core) ist bis heute eine solche zufällige und ungeordnete Wallet.

Wir merken uns: Unsere Schlüssel fliegen wahllos im Geldbeutel rum und haben keinen Bezug zueinander. Das ist unpraktisch und in der Nutzung auch mit erheblichen Risiken behaftet.


Bild: Mastering Bitcoin, Kapitel 5 – LINK




HD Wallets

Jetzt bringen wir etwas mehr Ordnung ins Spiel und kommen zur heute gängigen hierarchisch-deterministischen Wallet, die wahrscheinlich jeder von euch selbst benutzt.

Anders als beim vorherigen Beispiel stehen unsere Schlüssel in direkter Beziehung zueinander und wurden alle aus einem Generalschlüssel abgeleitet, auch bekannt als Seed.


Bild: Mastering Bitcoin, Kapitel 5 – LINK

Wir haben jetzt nur noch einen Generalschlüssel mit dem wir beliebig viele, ja sogar praktisch unendlich viele Schlüssel bzw. Adressen ableiten können. Diesen Generalschlüssel erzeugen wir mit Hilfe einer langen Zufallszahl, und diese Zufallszahl können wir auch in lesbare Wörter codieren, um einen einfachen Backup-Prozess zu ermöglichen:

worth unknown mean plastic neglect flip guilt library ripple explain destroy thing rival put usage tackle craft cheese

256 bit Entropie (+ 8 bit Checksumme) codiert als Mnemonic

ist deutlich praktischer als

fdfdbe27530940b219ec08ba4a10f0f05bab5dbbe6e83204

Die selben 256 bit Entropie in Hexadezimal

Auch wenn uns dieses geordnetere Konstrukt das Leben deutlich leichter macht stehen wir jetzt vor einem Problem.

Der Begriff hierarchisch bedeutet hier dass wir in einer Baumartigen Struktur von unten (Seed – Wurzel) nach oben (Krone) ableiten. Wie bei einem Baum gibt es hier keinen eindeutigen Weg, sondern wir können beliebige Verästelungen einschlagen auf dem Weg bis zur Krone.


Bild: Mastering Bitcoin, Kapitel 5 – LINK

Auf dieser Grafik sehen wir, wie aus dem Seed ein Schlüssel generiert wird. Aus diesem Schlüssel werden wiederum neue Schlüssel generiert, aus denen wiederum neue Schlüssel generiert werden, aus denen wiederum… immer so weiter.

Wer schon einmal einen vollständigen Familien-Stammbaum zusammengesetzt hat weiß, wie schwierig es sein kann überhaupt den Platz zu finden alles passend anzuordnen, da aus Uroma und Uropa ganz schön viele Urenkel enstanden sind.

Anders als bei einer Familie haben wir in unserer Wallet aber keine biologischen Grenzen, sondern können uns komplett austoben. :)

Ein Beispiel mit willkürlichen Zahlen:

Ich könnte aus dem Hauptschlüssel 1000 neue Schlüssel ableiten, dann den 476-sten nehmen und daraus 30 Schlüssel ableiten, dann den 4-ten Schlüssel nehmen und daraus 5.000.000 Schlüssel ableiten, dann den 3.993.127-sten Schlüssel nehmen und daraus dann einen Schlüssel ableiten.

Diesen Schlüssel nehme ich um mir eine Adresse zu erzeugen und meine Bitcoin abzusichern. Bis hier kein Problem.

Sobald ich aber mit meiner Mnemonic (d.h. dem Hauptschlüssel) wiederherstellen will muss ich den exakten Pfad zu dem Schlüssel der Adresse kennen um meine Bitcoin ausgeben zu können. Ich kontrolliere zwar mit meiner Mnemonic auch diesen einen Schlüssel, das bringt mir aber relativ wenig wenn ich nicht weiß wo er ist.




Derivation Paths

Jetzt da wir das Problem verstanden haben können wir eine relativ einfache Lösung dafür finden: Einen Wegweiser.

Den sogenannten Master Private Key (der direkt aus dem Seed abgeleitet wird) nennen wir ab jetzt m und den entsprechenden Master Public Key nennen wir M.

m/0 ist dann der erste Child Key von m, während m/1 der zweite Child Key von m wäre. Beide sind auch oben in der Grafik zu sehen!

Jetzt tasten wir uns Schrittweise im Ableitungspfad vor und benutzen um Verwirrung zu vermeiden Familienbezeichnungen aus Sicht der Eltern (m):

  • m/0/0 ist dann der erste Enkel vom ersten Kind.

  • m/1/0 ist dann der erste Enkel vom zweiten Kind.

  • m/0/0/0 ist dann der erste Urenkel vom ersten Enkel vom ersten Kind.

  • m/1/2/3/4 ist dann der fünfte Ur-Urenkel vom vierten Urenkel vom dritten Enkel vom zweiten Kind.

Langsam wird es kompliziert, aber ich denke wir haben verstanden wir der Wegweiser vom Prinzip her funktioniert. Falls nein: Lest euch diesen Abschnitt einfach mehrmals durch. Es ist anfangs vielleicht etwas abstrakt, das ist völlig normal.

Versuchen wir mal meinen absichtlich komplizierten Ableitungspfad von oben in dieses System umzusetzen:

Probier es erstmal selbst und klappe dann die Lösung auf

m/475/3/3993126/0

Achtung: Wir fangen in der Informatik mit 0 an zu zählen!

Den Ausdruck in Worten sparen wir uns besser.

Unser Problem wurde allerdings noch nicht gelöst. Wir stehen immernoch vor unendlich vielen Ableitungspfaden, die wir jetzt zwar eindeutig benennen können aber unsere Wallet müsste sie trotzdem erstmal alle absuchen, da sie alleine mit den 12 oder 24 Wörtern nicht weiß, wo sie hin muss.

Bei der unfassbar großen Anzahl an Möglichkeiten wäre dies schlichtweg unmöglich. Wenn jeder Entwickler sein eigenes Ableitungssüppchen kocht schadet das am Ende nur dem Nutzer da er nicht weiß wie er seine Schlüssel wiederherstellen kann.




Wir brauchen einen Standard

Und den gibt es! Um das einheitliche Ableiten zwischen verschiedenen Adresstypen und verschiedener Software zu ermöglichen hat man sich auf einen bestimmten Bauplan für den Ableitungspfad geeinigt.

Begonnen hat das in BIP-44, indem man eine bestimmte Funktion für jeden Ableitungsschritt vereinbart.

m/44'/0'/0'/0/0

  • Die erste Stelle steht für den Purpose, also welcher konkrete Standard verwendet wird. Der Endnutzer kann damit auch bereits auf den Adresstyp schließen den seine Wallet am Ende für ihn ableitet. In diesem Fall generieren wir traditionelle P2PKH (Legacy) Adressen, die mit einer 1 anfangen.

    Wir nehmen hier also immer den 45-sten Child Key.

  • Die zweite Stelle steht für den Coin Type, also um welchen Coin es gehen soll. Für Bitcoin nutzen wir 0, für das Bitcoin Testnet nutzen wir 1, für Litecoin nutzen wir 2, …

    Wir nehmen hier also den ersten Grandchild Key für Bitcoin.

  • Die dritte Stelle steht für den Account. Davon haben sicherlich die meisten schonmal etwas gehört und das ist auch die einzige Schnittstelle die man als normaler Nutzer mit dem Derivation Path hat.

    Wir nutzen diese Stelle im Pfad um uns effektiv „Unterkonten“ in unserer Wallet zu erstellen. Das hat einen reinen organisatorischen Vorteil, da wir bestimmte Adressen voneinander trennen und bestimmte Teile unserer Wallet für bestimmte Funktionen reservieren können (Sparen, Shoppen, Kinder, …).

    Da wir immer noch von einem Standard sprechen können wir diese Accounts einfach zwischen verschiedenen Wallets (Software) übertragen und landen immer bei den gleichen Schlüsseln und damit Accounts.

    Die Funktionen in der Ledger Live oder BitBox App machen genau das selbe. Sie kennen diesen Standard und wissen wo sie im Ableitungsbaum suchen müssen um zu anderen Accounts zu gelangen.

    Wir benutzen hier also 0 um in unserem „Standard Account“ zu landen und können dann durch erhöhen des Index beliebig viele Konten „erstellen“, die natürlich alle zu unserer Mnemonic gehören und jederzeit abgeleitet werden können. Wir gehen jeweils einfach auf einen anderen Ast.

  • Die vierte Stelle unterscheidet zwischen Receiving und Change Adressen. Um zu verstehen was das ist empfehle ich dir meinen Beitrag zu Unspent Transaction Outputs (UTXO).

    Wir benutzen 0 für normale Empfangsadressen und 1 für Wechseladressen.

Erst jetzt erreichen wir die eigentlichen Schlüssel die unsere Bitcoin kontrollieren!

  • Die letzte Stelle steht dann letztendlich für die eigentlichen Schlüsselpaare die wir für unsere Adressen alltäglich verwenden.

    Index 0 steht also für die erste Adresse bzw. die ersten Schlüssel, Index 1 für die zweite und immer so weiter. Wenn wir eine neue Adresse „generieren“ schaltet unsere Wallet einfach den Derivation Path an dieser Stelle um einen Index weiter. Jede Adresse bzw. jeder private Schlüssel hat einen eindeutigen Ableitungspfad.

Hier nochmal zusammengefasst in einer Grafik:

Bild: Greg Walker – learnmeabitcoin.com/technical/derivation-paths

m/44’/0’/0’/0/0

… leitet also die erste Receiving Bitcoin Legacy Adresse nach BIP-44 ab, die sich im ersten Account befindet.

m/84’/0’/1’/0/3

… leitet die vierte Receiving Bitcoin Native Segwit Adresse nach BIP-84 ab, die sich im zweiten Account befindet.




Meine Bitcoin werden nicht angezeigt

Mit unserem neuen Wissen können wir uns jetzt einen häufigen Grund für scheinbar „verschwundene“ Bitcoin erschließen: Etwas stimmt mit der Ableitung bzw. dem Ableitungspfad nicht.

Sichern wir einen Teil unserer Bitcoin z.B. in einem zweiten Account (z.B. Account #1: m/44’/0’/1’/…) und unsere Wallet weiß nichts davon, dann werden diese Bestände in der Übersicht auch nicht angezeigt. Natürlich kontrollieren wir diese Bestände trotzdem – unsere Bitcoin sind in Sicherheit, nur haben wir die entsprechende „Schublade“ noch nicht geöffnet.

Das erneute „Hinzufügen“ des Accounts führt dann dazu dass die Wallet Software den entsprechenden Pfad in der Ableitung absucht und alle Bestände die sie dabei findet auch wieder anzeigt.

Bei der BitBox02 ist dies zumindest so der Fall. Nutzt man seine BitBox02 an einem neuen Rechner oder Android Smartphone bzw. installiert die BitBox App neu, dann werden nicht automatisch alle Accounts abgesucht. Man muss manuell alle Accounts wieder aktivieren.

Edit: Mit der neuen BitBoxApp-Version (Juni 2023) werden Accounts automatisch abgesucht. Das Problem sollte also nicht mehr auftreten! :)

Gap Limits

In der Regel zeigt euch eure Wallet Software immer die nächsten 20 Adressen an, die noch nicht benutzt worden sind. Diese Zählung beginnt immer ab der letzten verwendeten Adresse. Bedeutet: Auch wenn Adressen 1-19 unbenutzt sind, ihr aber Adresse 20 verwendet habt, dann werden euch jetzt die Adressen 21-40 angezeigt. Lasst euch davon also nicht verwirren.

Es kann (z.B. nach einem CoinJoin) passieren dass eure Bitcoin auf Adressen mit einem sehr hohen Index landen, der vom Gap Limit eurer Software nicht abgedeckt ist, d.h. euch werden die Bestände nicht angezeigt.

Genau das ist z.B. einem Nutzer in diesem Thread passiert:

Die Lösung lautet hier, ähnlich wie mit den Accounts, die entsprechenden Adressen einfach abzusuchen. Software wie die Sparrow Wallet unterstützen hierfür das manuelle erhöhen des Gap Limits, also der Anzahl an Adressen die nach der Adresse mit höchstem Index abgesucht werden sollen.

Auch die BitBox App kann man mit einem Argument starten um das Gap Limit anzupassen:




Verstecken spielen

Wer jetzt auf die großartige Idee kommt dass man manuell seine Bitcoin auf einem unkonventionellen Ableitungspfad absichern könnte, damit man selbst mit der Mnemonic die richtigen Schlüssel zunächst nicht findet, den versuche ich hier direkt aufzufangen.

Nein, bitte macht das nicht!

Es ist grundsätzlich nicht ratsam und immer mit Risiken verbunden vom Standard abzuweichen.

Gründe die gegen dieses Vorgehen sprechen:

  • Das Verstecken im Ableitungspfad bietet keine Sicherheit, sondern höchstens Zeit. Mit der Mnemonic hat ein Angreifer eigentlich alles was er wissen muss, es ist nur eine Frage der Zeit bis er den richtigen Schlüssel findet. Es ist die Suche nach der Nadel im Heuhaufen – aber die ist nicht unmöglich.

  • Es gibt standardisierte Verfahren für mehr Sicherheit. Zum Beispiel eine optionale Passphrase, die tatsächlich auch mehr Sicherheit bietet.

  • Ihr macht es euren Erben noch komplizierter als es wahrscheinlich ohnehin schon ist.

  • Nicht jede Wallet Software erlaubt es euch einen beliebigen Ableitungspfad zu besuchen. Ihr schränkt eure Optionen damit extrem ein.

Bleibt beim Standard, d.h. das einzige das ihr am Derivation Path anpasst ist der Account Index. Das wars.




Extended Keys

Nachdem wir jetzt verstanden haben wie HD Wallets funktionieren können wir uns erweiterte Schlüssel wie den beliebten xpub (Extended Public Key) genauer anschauen.

Am besten schauen wir uns dafür wieder Ableitungspfade an, konkret diese drei Public Keys bzw. Adressen:

(Erinnerung: Großes M als Abkürzung für Public Key)

  • M/84’/0’/0’/0/0
  • M/84’/0’/0’/0/1
  • M/84’/0’/0’/0/2

Hat man einen der drei Schlüssel kann man damit nicht auf die anderen beiden schließen. Geschwister können sich untereinander nicht ableiten (genauso wenig wie sie sich biologisch fortpflanzen können – die Analogie funktioniert immer noch). Nur der Parent Key kann alle Child Keys ableiten, nicht anders herum. Eltern können Kinder kriegen, aber Kinder keine Eltern.

Wenn wir jemandem eine Bitcoin Adresse für eine Bezahlung geben, dann möchten wir schließlich nicht dass er damit alle anderen Adressen ableiten kann und damit unsere Bestände kennt. (Hinweis: Könnte er sowieso nicht solange er den Public Key nicht kennt – Dieser wird bei einer Transaktion aber veröffentlicht)

Trotzdem brauchen wir einen Weg unsere Adressen „in einem Schlüssel“ zu speichern, ohne unsere kritischen Geheimnisse wie z.B. die Mnemonic Preis zu geben. Die Wallet Software die wir mit unserer Hardware Wallet verwenden muss zwar unsere Transaktionen und Adressen kennen, darf aber nicht an Private Schlüssel gelangen.

Die Lösung: Wir verwenden den Public Key des jeweiligen Accounts, also zum Beispiel:

  • M/84’/0’/0’

… kann alle Adressen bzw. alle Public Keys (inkl. Change) des Accounts #0 derivieren – aber keine Private Keys!

hierarchical-deterministic-wallets (1)

GIF: Greg Walker – learnmeabitcoin.com/technical/hd-wallets

Diesen 256 bit Schlüssel codieren wir zusammen mit dem sogenannten Chain Code, der für das derivieren notwendig ist in einen 512 bit Extended Public Key (xpub):

xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9

Was ist der Chain Code? Der Einfachheit halber habe ich diesen Teil des Ableitungsprozesses während dieses Beitrages unterschlagen, da er für den normalen Nutzer auch völlig irrelevant ist. Ich empfehle Kapitel 5 aus Mastering Bitcoin oder die unten verlinkten learnmeabitcoin Seiten wenn man hier noch tiefer einsteigen will. Selbiges gilt für das Konzept der gehärteten Ableitung (Hardened Derivation).




Links

Forum:

Der Beitrag ist länger geworden als gedacht :sweat_smile:

Hoffe es war hilfreich und ihr konntet was neues dazu lernen – Wie immer sofort mit Kritik und Feedback melden sollte irgendetwas inhaltlich nicht stimmen!

41 „Gefällt mir“

Wie immer spitze @sutterseba :slight_smile:

Freue mich schon drauf, wenn du das ganze jetzt auch noch für ein Video auf dem Community-Kanal aufbereitest :stuck_out_tongue: /jk

P.S. Riecht ja schon fast wieder nach einem Gastbeitrag (wenn du willst) :smiley:

3 „Gefällt mir“

Großartig! Vielen Dank!

1 „Gefällt mir“

Es gibt noch ein interessantes Detail ganz am Anfang der Kette, welches mir bisher nicht aufgefallen ist. Und zwar wie man vom Mnemonic zum Seed kommt.

Die 256 Bit Zufallszahl (plus 8 Bit Checksumme = 264 Bit) entspricht ja dem Mnemonic. Das ist also äquivalent und das könnte man also jederzeit hin- und herrechnen.

Der Seed wird allerdings nicht direkt aus den 264 Bit (wie ich dachte) abgeleitet, sondern aus dem String des Mnemonic. Der String des Mnemonic plus der String „mnemonic“ plus der String eines optionalen Passwortes gehen in die PBKDF2 Hashfunktion ein. Das sieht man hier sehr schön:

https://learnmeabitcoin.com/technical/mnemonic#mnemonic-to-seed

Ich dachte bisher, man könnte den Mnemonic einfach in andere Sprache „übersetzen“, da es nur auf den Index innerhalb der jeweiligen Wortlisten ankommt. Das ist aber nicht der Fall, da direkt der String in die Hashfunktion eingeht.

Das sieht man auch, wenn man in Ian Colemans Converter Tool oben die Sprachen hin- und herschaltet. Die Zufallszahl (Entropy) bleibt gleich, aber der BIP39 Seed und damit sämtliche Keys und abgeleiteten Adressen ändern sich komplett.

Man kann also seine Mnemonic Phrase nicht mittels andersprachiger Wortlisten in eine andere Sprache „übersetzen“.

3 „Gefällt mir“

Ist mir auch nicht aufgefallen bisher…

Das ist denke ich auch der Hauptgrund warum sich das nicht wirklich etabliert hat bzw. etablieren wird. Wäre schon praktisch wenn man einfach untereinander „übersetzen“ könnte und die Sprache beim Import komplett egal wäre.

Ich frage mich warum die anderen Sprachen nicht einfach an die englische Wordlist gekoppelt werden, d.h. in den HMAC geht immer der englische String rein, aber ich kann die codierte Entropie in den anderen Sprachen austauschen – zurückrechnen auf die binäre Entropie ist ja kein Problem und immer eindeutig solange es standardisierte Listen gibt. Wallets müssen einfach nur das umcodieren in die englische Mnemonic unterstützen und das wars.

1 „Gefällt mir“

@sutterseba

Einfach immer wieder absolute Spitze deine Tutorials! Besten Dank! :slightly_smiling_face:

2 „Gefällt mir“

Gibt es denn eine grenze? oder sind es echt unendlich viele?

Ja, gibt es. Deswegen auch die Betonung auf praktisch unendlich. Zwei verschiedene Grenzen um genau zu sein:

  1. Es gibt maximal 2^{160} unterschiedliche Adressen bzw. 2^{256} unterschiedliche private Schlüssel. Theoretisch kontrolliert jeder von uns mit seiner Mnemonic alle Bitcoin die es gibt, da man es mit dem Ableitungspfad beliebig übertreiben und theoretisch unendlich viele Schlüssel derivieren kann. Das wäre dann aber kaum noch ein Unterschied (eigentlich gar keiner) zu einem ganz normalen Brute Force Angriff den wir ja schon häufig diskutiert haben. Siehe hier.

    Wäre man dazu in der Lage (Spoiler: Geht nicht) trifft man irgendwann zwangsläufig auf eine Kollision bzw. hat alle Schlüssel die es überhaupt geben kann abgedeckt und damit „die Grenze“ erreicht.

  2. Innerhalb von einem Pfad bzw. „einem Account“ kann man maximal 2^{32} Schlüssel derivieren. Das liegt daran dass der gewünschte Index der beim Derivieren in den HMAC geworfen wird maximal 32 bit haben darf. Durch die Möglichkeit der gehärteten Ableitung wird dieser mögliche Bereich sogar nochmal halbiert auf maximal 2^{31} gehärtete und 2^{31} nicht gehärtete Schlüssel.

    In der Praxis können wir also in einem Account nur 2^{31} Adressen derivieren.

    Nach m/84’/0’/0’/0/2147483648 ist also erstmal Schluss. Wir können aber natürlich in jedem Schritt 2^{32} mal ableiten, und landen wir letztendlich bei Grenze 1 von oben.

Hoffe ich habe da keinen Denkfehler drin :sweat_smile:

3 „Gefällt mir“

Stimmt das wirklich? Nur weil es unendlich viele Ableitungspfade gibt, heißt das nicht, dass alle Ableitungspfade sich auch überschneiden. Hast du da eine Quelle?

Ich habe keine Quelle, aber eine grobe (hoffentlich richtige) Abschätzung.

Bei den Betrachtungen geht eine ganz entscheidende Annahme ein:

Man nimmt üblicherweise an, man weiß es aber nicht, dass eine Hashfunktion die Hashes zufällig im Ergebnisraum verteilt. Deshalb rechne ich hier wie bei einem Zufallsexperiment.

Fall 1 - Nicht BIP-konform

Wenn man sich nicht an BIP44 etc. hält, kann man dem Ableitungspfad beliebig viele Unterebenen hinzufügen, oder sogar den Ableitungsindex über 2³² hinaus fortführen.
Dadurch erhält man tatsächlich unendlich viele Versuche, mit der Ableitungsfunktion einen bestimmten Private Key zu treffen.

→ Auch wenn es also fast 2²⁵⁶ Private Keys gibt, werde ich bei einem echten Zufallsexperiment mit unendlich vielen Versuchen jeden davon irgendwann erwischen.

Fall 2 - Einigermaßen BIP-konform

Wenn man sich an die BIPs hält, sieht es wie @sutterseba schon erklärt hat, anders aus.

Angenommen auf jeder der fünf Ableitungsebenen habe ich wegen des 32 Bit Ableitungsindexes nur 2³² Möglichkeiten. Dann erhalte ich aus meinem Seed insgesamt (2³²)⁵ = 2¹⁶⁰ Private Keys.

Gleichzeitig gibt es bis Native Segwit wegen des RIPEMD160 Hashes nur 2¹⁶⁰ Adressen. Für jede dieser Adressen gibt es also im Mittel ca. 2²⁵⁶ / 2¹⁶⁰ = 2⁹⁶ gültige Private Keys. Wenn ich die Private Keys nur danach unterscheide (klassifiziere), für welche Adresse sie gültig sind, gibt es entsprechend nur ca. 2¹⁶⁰ unterscheidbare Private Keys.

→ Die Wahrscheinlichkeit mit 2¹⁶⁰ Zufallsversuchen einen gültigen Private Key für eine bestimmte der 2¹⁶⁰ Adressen zu treffen beträgt: 1 - e⁻¹ ≈ 63 % (Link). Du wirst also für ein Drittel aller möglichen Adressen keinen passenden Private Key von deinem Seed ableiten können.

Fall 3 - Komplett BIP-konform

Falls man den Ableitungspfad nach Standard teilweise festlegt, schränkt man die Zufallsversuche weiter ein.

Für eine Native Segwit Bitcoin-Ableitung ist z.B. der Purpose 84 und der Coin 0. Entsprechend habe ich nur noch 3 Ableitungsebenen frei zur Verfügung, was (2³²)³ = 2⁹⁶ möglichen Private Keys entspricht.

→ Damit ist es praktisch unmöglich einen gültigen Private Key für eine bestimmte Adresse zu treffen. Die Wahrscheinlichkeit beträgt: 1 - 1/exp(2⁻⁶⁴) ≈ 0 %.

Nebenbei sieht das ganze anders aus, wenn man (vollkommen BIP-konform) einfach viele verschiedene Seedphrases und Passphrases durchprobiert. Dabei hat man so viele Möglichkeiten, dass man für jede bestimmte Adresse einen Private Key treffen sollte.

2 „Gefällt mir“

@sutterseba großartige Arbeit!

Ich hätte jedoch ein kleines Verständnisproblem bzgl. der Indizes die für die Ableitungsfunktionen verwendet werden. Aus einen extended Key können 232 Child-Schlüssel abgeleitet werden. 231 mittels normaler Ableitung über den xpub... und weitere 231 mittels gehärteten Ableitung über den xprv... .

Bedeuten das, dass der Index-Wertebereich zwischen [0 und 231 - 1] ausschließlich für die normale Ableitung verwendet wird, während der Bereich zwischen [231 und 232 - 1] nur für die gehärtete Ableitung verwendet wird?

Wie würden dann die jeweiligen Ableitungspfade des fünften Schlüssels aussehen?

  • Normale Ableitung: m/84/0/0/0/4
  • Gehärtete Ableitung: m/84/0/0/0/2417483652

Wäre das so richtig oder wird für die gehärtete Ableitung eine vereinfachte Darstellung verwendet?

2 „Gefällt mir“

Die Indizes werden wie du richtig schreibst dann einfach in zwei Hälften aufgeteilt, 0 bis 2^{31} -1 für normale und 2^{31} bis 2^{32} -1 für gehärtete Derivation.

Um das ganze lesbar zu halten wird ab 2^{31} wieder bei 0 angefangen und ein ' angehängt dass auf die gehärtete Ableitung deutet.

Die beiden Schlüssel würde man also so angeben:

  • Normale Ableitung: m/84’/0’/0’/0/4
  • Gehärtete Ableitung: m/84’/0’/0’/0/4’

Siehe Hardened Derivation in Mastering Bitcoin:

3 „Gefällt mir“

Super, wieder etwas dazugelernt! Danke dir :+1:

Also du meinst, obwohl die Ableitungspfade selbst sich womöglich nicht überschneiden, findet die Überschneidung bei den daraus generierten Adressen statt. Verstehe.

Danke @sutterseba , an dem Brett kann ich noch eine Weile kauen :joy:

Hallo in die Runde,
vielen Dank @sutterseba für den Artikel, der mir dass Verständnis erleichtert, auch wenn ich den Artikel noch häufiger lesen werden.
2 Fragen habe ich dazu: Roman erwähnte mal in einem Tutorial, dass man häufiger verschiedene der 20 Adressen nutze sollte, die einem die Bitbox zum empfangen von Coins anbietet, da dies die Sicherheit erhöhen würde. Wieso erhöht das verwenden verschiedener Adressen die Sicherheit, oder habe ich das falsch verstanden?
Wenn ich 3x Sats im Wert von 10 Euro auf 3 Adressen empfangen habe, kann ich dann wieder nur 3x 10 Euro verschicken oder auch 30 Euro auf einmal?
Für Antworten oder weiterführende Links wäre ich dankbar.

Eine transaktion besteht immer aus dem einlösen von unspent transaction outputs (utxo), stell sie dir vor wie Geldscheine. Du kannst dabei beim transferieren mehrere utxos zusammen führen, wie du auch 100 € mit 5x 20€ Scheinen bezahlen kannst. Der Adressat erhält die Summe der utxo als neuen einzelnen utxo/Schein, also quasi die 20er scheine fusionieren zu einem 100er Schein. Diese utxo müssen nicht aus einer Adresse stammen, sondern werden automatisch von deiner Wallet Software möglichst passend zusammen gesucht. Eine manuelle Kontrolle über die Auswahl der zuversendenden utxo, nennt sich coin control.

1 „Gefällt mir“

Wenn du einen Betrag transferierst der Inklusive der Fees an den miner nicht vollständig durch ganze utxo geteilt werden kann, wird einer der utxos aufgeteilt und der Rest Betrag wird als Wechselgeld transaktion an die eigene Adresse zurück geschickt.

Deine wallet software hat den Zugriff zu allen utxo auf all deinen Adressen. Und ordnet sie deinem Konto zu, abgesehen von deiner Börse erkennt der Rest des Netzwerkes / die Welt da draußen, bösartige hacker,… Keinen Zusammenhang zwischen deinen Adressen. Sie können nicht sagen, wie vielen Entitäten eine Gruppe von Adressen zuzuordnen ist, solange diese Adressen sich nicht in ungeschickterweise durch zusammenführen von utxos entblößen.

Keine Zuordnung von Adressen bzw. Utxos (deine Geldscheine) bedeutet auch keine Zuordnung deiner Adresskontoständen und damit keine genaue Bestimmung deines Gesamtkontostandes.
Wenn du eine Transaktion tätigst, deklarierst du eine Herkunft und ein Ziel sowie den cryptographischen Beweis (Signatur), dass du über die besagte Transfermenge, basierend aus der Summe von UTXOs, verfügen kannst (du besitzt den private key/die Geldscheine im portmonai).
Da diese transaktion öffentlich auf der blockchain gespeichert ist, kann jeder sich den Kontostand und die Transaktionshistorie der Herkunftsadresse ansehen. Du möchtest nicht durch eine Transaktion deinen gesamten Kontostand offenlegen.

Es ist besser für die Privatsphäre wenn du jedes mal eine andere Adresse nutzt. Welche das der nächsten 20 ist spielt keine Rolle. Nimm einfach immer die, die du von der BitBox App bekommst.

Zur zweiten Frage hier reinlesen: