Praktikumsübung Bitcoins

Praktikumsübung Bitcoins
Gegeben ist der Ablauf der Adresserstellung bei Bitcoin
Für jede Transaktionen wird ein neues Schlüsselpaar generiert. Hierfür wird das ECDSASignaturverfahren genutzt. Erst einmal besitzt jeder Benutzer ein sogenanntes „Wallet“, also eine
Art elektronisches Portemonaie mit einem privaten Schlüssel. Dieser private Schlüssel wird geheim
gehalten. Aus dem privaten Schlüssel wird nun ein öffentliches Schlüsselpaar (x,y) von 2x32 Bytes
Größe generiert. Aus diesem öffentlichen Schlüsselpaar wird nun eine Bitcoin- Adresse.
1. Es wird eine 65- Byte- Zahl gebildet, indem ein Byte mit dem Wert 4, x und y direkt
hintereinandergehängt werden. Hieraus ergibt sich z.B.
043b7fdb1f4c04f06f335f52983367b776d1dfa116192627e31954d7e4db952aa58b6ad923b36b88498
4868d1042914976bb09f48dd03f67e145ac0ce1da71c5c7
2 . Auf die eben erhaltene 65- Byte- Zahl wird erst einmal SHA-256 angewendet. Hierdurch erhält
man eine 32-Byte Zahl:
2f827a20c7e43f3ea2b3f75ef91b824913e2d29b122cedc33b2f8c7edc4ceef3
3. Auf die erste SHA-2-Zahl wird anschließend RIPEMD-160 angewendet. Man erhält:
00f3b469cea957b2cecca03e974d422d2c2e72a4ae
4. Nun wird die Versionsnummer vorne angehängt (hier ist es 00 für das Hauptnetzwerk) man
erhält:
0000f3b469cea957b2cecca03e974d422d2c2e72a4ae
5. Nun wird auf das Ergebnis wiederum SHA 256 angewendet. Man erhält:
310a493054bf163b0562e2b73efcd98f3794073bb69403f70de1be70b3f618c4
6. Nun folgt eine weitere Anwendung von SHA-256. Man erhält:
9ddfc8cd007589ec4d154c259a4d728a528a4dcaf6cfa3475b653fa2a2e3adc9
7 – Die Checksumme sind die letzten 4 Bytes des zweiten SHA-2-Wertes:
a2e3adc9
8 – Die gesamte Bitcoin-Adresse ist der erste RIPEMD-160-Hash plus die Checksumme, die
angehängt wird:
0000f3b469cea957b2cecca03e974d422d2c2e72a4aea2e3adc9
9 – Meistens wird eine Bitcoin-Adresse als Base-58-Codierung dargestellt. In diesem Beispiel ist
dies:
1C7pZvW5ZXm5cL9nmoyq1ovzU
Anhang: Base-58-Symboltabelle
Value
0
4
8
12
16
20
24
28
32
36
40
44
48
52
56
Character
1
5
9
D
H
M
R
V
Z
d
h
m
q
u
y
Value
1
5
9
13
17
21
25
29
33
37
41
45
49
53
57
Character
2
6
A
E
J
N
S
W
a
e
i
n
r
v
z
Value
2
6
10
14
18
22
26
30
34
38
42
46
50
54
Character
3
7
B
F
K
P
T
X
b
f
j
o
s
w
Value
3
7
11
15
19
23
27
31
35
39
43
47
51
55
Character
4
8
C
G
L
Q
U
Y
c
g
k
p
t
x
Aufgabe 1:
Programmieren Sie ein eigenes elektronisches Wallet, das Bitcoin- Adressen erstellt und auf der
lokalen Festplatte abspeichert (diese Daten müssen nicht verschlüsselt werden). Simulieren Sie
dafür den Ablauf der Bitcoin- Adresserstellung aus einem gegebenen privaten Schlüssel. Hierfür
dürfen Sie die fertige Lib „bitcoin.lib“ benutzen, die Funktionen für SHA und RIPEMD bereit stellt
(Sie müssen also die Hashverfahren nicht noch einmal selbst programmieren). Die Beschreibung
der Funktionen von „bitcoin.lib“ befindet sich im Anhang.
Aufgabe 2:
Erweitern Sie Ihr Wallet so, dass es auch Transaktionen erstellen und in eine Blockchain einhängen
kann. Die Blockchain soll sich in diesem Fall als Datei auf der lokalen Festplatte befinden und neue
Transaktionsblöcke mit maximal einer Transaktion pro Block sollen immer hinten angehängt
werden. Sie müssen also keine verkettete Liste und keine Merkle- Bäume programmieren- es reicht
die Verwendung von „fread“, „fseek“ und „fwrite“ aus.
Aufgabe 3:
Um die Blockchain abzusichern, wird normalerweise mit den Transaktionsdaten eine partielle HashInvertierung durchgeführt. Die Lösung dieser schwierigen Aufgabe durch bestimmte
Netzwerkteilnehmer mit viel Rechenleistung (die sogenannten Miner) sichert die Blockchain gegen
Angriffe ab. Simulieren Sie das Mining in Ihrem Programm durch ein einfacheres Problem, das in
einer vernünftigen Zeit auch auf Standard- PCs lösbar ist.
Vorschläge:
–
–
–
–
Betrachten des Datenblocks als lange Zahl und Erstellen eines zusätzlichen Prüfblocks.
Dieser enthält die nächste Primzahl, die auf die Zahl folgt, die entsteht, wenn man den
Datenblock als lange Zahl betrachtet. Dieses Problem kann z.B. mit einer
Ganzzahlbibliothek wie miracl (Windows) oder GMP (Linux) gelöst werden.
Erstellen einer Signatur z.B. durch einen SHA- Hash oder einen anderen Hash Ihrer Wahl
Erstellen einer Block- Prüfsumme, z.B. mit CRC 32. Dies ist zwar nicht kryptographisch
sicher, aber schnell auszuführen.
Berechnen einer partiellen Hash- Invertierung nur für einen kleinen Teil des Datenblocks
Die Bitcoin-Lib
Funktionen:
MakePublicKey(char *PrivateKey, char *PublicKey, long int Counter)
Erstellt aus einem privaten Schlüssel-String einen öffentlichen Schlüssel, der 65 Bytes groß ist und
die Form hat, die man für die Adresserstellung benötigt. Die Art der Erstellung wurde hier etwas
vereinfacht: Gleiche Werte für den Zähler erzeugen bei gleichem privaten Schlüssel auch gleiche
öffentliche Schlüssel.
SHA_256(char *Dst, char *Src, long int BlockLen)
Führt einen SHA256-Hashvorgang aus. Dst ist der Zielblock, Src ist der Quellblock. Es wird immer
nur ein Block gehasht und sofort finalisiert. Mit dieser Funktion können keine Dateien gehasht oder
signiert werden.
RIPEMD_160(char *Dst, char *Src, long int BlockLen)
Führt einen RIPEMD160-Hashvorgang aus. Dst ist der Zielblock, Src ist der Quellblock. Es wird
immer nur ein Block gehasht und sofort finalisiert. Mit dieser Funktion können keine Dateien
gehasht oder signiert werden.
CopyString(char *Dst, char *Src, long int BlockLen)
Funktioniert wie „strcpy“. Der Unterschied ist hier, dass mit dieser Funktion Strings kopiert werden
können, die Null- Bytes enthalten.
SubString(char *Dst, char *Src, long int StartPos, long int EndPos)
Kopiert einen Teil eines Quell-Strings nach „Dst“. StartPos und EndPos beziehen sich auf den
Quellstring „Src“. Der Zielstring „Dst“ wird NICHT mit 0 abgeschlossen!
void OutputString(unsigned char *Dst, long int Len, bool LF);
void OutputStringBase58(unsigned char *Dst, long int Len, bool LF);
Diese Funktionen diesen zur Ausgabe von Strings, die auch Nullzeichen enthalten können. Wenn
LF (Line Feed) true ist, wird ein Zeilenumbruch angehängt.
Vordefinierte Datenstrukturen:
unsigned char BTCAddress[33]; // Bitcoin-Adressen können 25-33 Bytes lang sein
unsigned char BTCKEY[65]; // Public-Keys sind immer 65 Bytes lang, das MSB ist eine 4
struct BTCTransaction // Minimal erforderlicher Transaktionsblock für die Blockchain
{
unsigned char BlockHash[32];
long int PrevBlockPos;
BTCAdress Dst;
BTCAddress Src;
double BTCValue;
};