Es ist bei Bitcoin sehr wichtig das Konzept zu verstehen, das man keine Online Verbindung für das generieren einer Bitcoion Wallet Adresse benötigt.
Das geht komplett Offline. Und ohne separaten Server, eine Webseite oder einen besonderen Service. Es wird nur etwas Mathe benötigt. Mit Java sind nur ein paar Zeilen nötig.
1. privaten Key erzeugen, dazu brauchen wir nur einen guten Zufallsgenerator der uns 32 Byte erzeugen kann. Könnte mal auch auswürfeln.
2. validieren ob der Key gültig ist
Hier der dokumentierte Code: …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package de.wenzlaff.twhash; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; /** * Privaten Bitcoin Key erzeugen. * * @author Thomas Wenzlaff */ public class CreatePrivatKey { public static void main(String[] args) throws NoSuchAlgorithmException { byte[] privaterKey = new byte[PrivateKey.PRIVATE_KEY_GROESSE]; // immer geheim halten do { SecureRandom secRandom = SecureRandom.getInstanceStrong(); System.out.println("Verwende Algorithmus (je nach System) : " + secRandom.getAlgorithm()); secRandom.nextBytes(privaterKey); } while (!PrivateKey.isBitcoinPrivateKeyGueltig(privaterKey)); System.out.println("Privater Key in String präsenations Format : " + Arrays.toString(privaterKey)); System.out.println("Privater Key (32 Byte bei 8 Bit = 256 Bits = 64 Hex) erzeugen: " + Transform.bytesToHex(privaterKey)); // 24e8621ad9cab81a1aa5793665b376a58cfcb15fab02b28fa76b281401b7440c } } |
Das ist schon alles, wir haben einen eigenen Bitcoin private Key erzeugt! Hurra! Wenn jemand anderes den gleichen Key generieren will gibt es 2 hoch 256 Möglichkeiten. Eine astronomisch große Zahl.
Genau sind aber nicht alle privaten Keys in Bitcoin gültig. Die Keys müssen kleiner sein als Hex:
0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4140
weil Bitcoin Elliptic Curve Cryptography (ECC) nutzt (secp256k1). Das schränkt uns aber nicht wirklich ein. Ist der erzeugt Key zu groß, berechnen wir einfach einen neuen. Hier die Klasse die den Key validiert:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
package de.wenzlaff.twhash; import java.math.BigInteger; /** * Checkt die Gültigkeit eines Bitcoin privat Keys. * * @author Thomas Wenzlaff */ public class PrivateKey { /** * Die Länge des public Key in Bitcoin. 32-Byte. */ public static final int PRIVATE_KEY_GROESSE = 32; /** * Der max. mögliche private Key Wert. Von 0x1 * * bis * * 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 * 4140; * * Siehe https://en.bitcoin.it/wiki/Private_key und * https://en.bitcoin.it/wiki/Secp256k1 */ private static final String MAX_ECDSA_PRIVATE_KEY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140"; /** * Checkt ob der private Key gültig ist. D.h. ob er die maximal gültige Größe * nicht übersteigt. * * @param privaterKey der zu überprüfende Key * @return wenn der Key gültig ist wird true geliefert, wenn er ungültig ist * false. */ public static boolean isBitcoinPrivateKeyGueltig(byte[] privaterKey) { if (privaterKey.length != 32) { throw new IllegalArgumentException("Der private Key ist nicht 32-Byte lang"); } BigInteger maxBitcoinPrivateKeyWert = new BigInteger(MAX_ECDSA_PRIVATE_KEY, 16); BigInteger key = new BigInteger(Transform.bytesToHex(privaterKey), 16); System.out.println("Privater Key in Dezimal : " + key); System.out.println("Maximal möglicher privater Key in Dezimal : " + maxBitcoinPrivateKeyWert); return key.compareTo(maxBitcoinPrivateKeyWert) < 0 ? true : false; } } |
Die Ausgabe des Programms liefert dann den private Key in der letzen Zeile als Hex:
1 2 3 4 5 |
Verwende Algorithmus (je nach System) : NativePRNGBlocking Privater Key in Dezimal : 93750168568141633471316910723068691361065235165031563689710894762687964706633 Maximal möglicher privater Key in Dezimal : 115792089237316195423570985008687907852837564279074904382605163141518161494336 Privater Key in String präsenations Format : [-49, 68, -73, 10, -49, 48, -106, 20, 106, -41, -54, -100, 17, -89, -91, 23, -124, -78, -91, 18, 87, 0, 14, -49, -103, 12, -89, 109, 101, 96, -9, 73] Privater Key (32 Byte bei 8 Bit = 256 Bits = 64 Hex) erzeugen: cf44b70acf3096146ad7ca9c11a7a51784b2a51257000ecf990ca76d6560f749 |
Nun haben wir schon einen gültigen privaten Key für Bitcoin erzeugt. Wer den privaten Key cf44b70acf3096146ad7ca9c11a7a51784b2a51257000ecf990ca76d6560f749 dann mal validieren will, kann ihn ja mal hier im Feld 0 – Private ECDSA Key eingeben und auf „Send“ klicken. Schon wird online die gültige Bitcoin-Adresse 1JqbJP3N2jvmbz3nQzzPYjeXtWbcCTMHUD bzw. Konto generiert.
Der private Key muss ja immer geheim gehalten werden. Deshalb bitte nichts auf diese nun allgemein bekannte Adresse überweisen 😉 Aber es gibt ja auch noch genügend andere Adressen 😉
Nun kommt der eigentlich viel spannenderer Task, aus dem privaten Key den public Key mit Java zu generieren. Das geht mit der Elliptic Curve Cryptography (ECC) (secp256k1). Auf der obigen Online-Seite habe wir das ja schon gemacht. Aber eben nicht offline und mit Java. Dann mal los, aber nicht mehr heute …
Kleine Programmier challenge: Wer will, kann mir den Java Code per E-Mail senden, wie am besten aus dem privaten Key ein public Key erzeugt wird. Auf wunsch nenne ich dann auch den Namen und stelle die verschiedenen Möglichkeiten vor.