Wielu ludzi zastanawia się, dlaczego nie możemy mnożyć kluczy publicznych przez siebie w ECDSA. Możemy dodawać punkty na krzywej eliptycznej, odejmować je, mnożyć punkt przez jakąś liczbę, czy też wykonywać analogiczne dzielenie (wykorzystując inwersję). Głównym powodem takiego stanu rzeczy jest ukryty argument, o którym często się zapomina: punkt bazowy.
Bardzo często ludzie myślą o takich rzeczach, jak "dzielenie punktu na pół" w podobny sposób, w jaki można to zrobić na liczbach całkowitych, w innych językach programowania: jeśli mamy 9/10, to nam daje zero jako wynik. W przypadku ECDSA, takie reguły nie działają.
Aby lepiej zrozumieć, jak mnożenie punktu przez punkt mogłoby być zdefiniowane, możemy wziąć krzywą eliptyczną, którą kiedyś miałem w swoim awatarze: "p=79,n=67,base=(1,18),bits=7". Całość wygląda dość prosto, każda współrzędna zajmuje tylko jeden bajt i możemy z łatwością w pełni prześledzić wszystko, co tam się dzieje, bez dodawania jakichkolwiek optymalizacji, zwyczajnie sprawdzając wszystko metodą brute-force.
Zatem, zaczynamy od naszego p=79. Możemy łatwo ustalić, że mamy do czynienia z liczbą pierwszą, a także znaleźć najbliższy punkt, spełniający słynne równanie: y^2=x^3+7. Wszystkie liczby są na tyle małe, że możemy łatwo utworzyć bitmapę o rozmiarach 79x79 z czarnym tłem, a następnie ustawić białe piksele w miejscach, w których pozycja (x,y) spełnia wcześniej podane równanie. Co więcej, możemy nawet spróbować zrobić to samo, używając nieco większych liczb, uzyskując piękną tapetę, przypominającą gwiazdy na nocnym niebie.
Ciekawostka od tłumacza: użytkownik vjudeu w międzyczasie opublikował na swoim GitHubie pliki PNG z wszystkimi takimi krzywymi eliptycznymi, gdzie p<1000: https://github.com/vjudeu/curves1000
W ten sposób, możemy łatwo znaleźć najbliższy punkt, wynoszący (1,18) w tym przypadku. Dodatkowo, możemy policzyc wszystkie kropki i zauważyć, że mamy 66 punktów, zaś 67. wartość wynosi po prostu (0,0) i jest punktem w nieskończoności (który możemy uzyskać później, gdy spróbujemy dodać do siebie pierwszy i ostatni punkt).
Zatem, zacznijmy od punktu bazowego i utwórzmy listę wszystkich punktów:
d= 2, x=60, y=10
d= 3, x=15, y= 8
d= 4, x=49, y= 5
d= 5, x=42, y=54
d= 6, x=59, y=12
d= 7, x=61, y=10
d= 8, x=43, y=35
d= 9, x=37, y=69
d=10, x=26, y=19
d=11, x=18, y=54
d=12, x=12, y=47
d=13, x=39, y=47
d=14, x= 9, y= 5
d=15, x=63, y=63
d=16, x=19, y=25
d=17, x=75, y=41
d=18, x=21, y=74
d=19, x=68, y=63
d=20, x=29, y= 8
d=21, x= 6, y=12
d=22, x=45, y=19
d=23, x=35, y=71
d=24, x=66, y=41
d=25, x=28, y=32
d=26, x=17, y=41
d=27, x=14, y=67
d=28, x=74, y=35
d=29, x=23, y=18
d=30, x=55, y=61
d=31, x=41, y=35
d=32, x= 8, y=60
d=33, x=27, y=63
d=34, x=27, y=16
d=35, x= 8, y=19
d=36, x=41, y=44
d=37, x=55, y=18
d=38, x=23, y=61
d=39, x=74, y=44
d=40, x=14, y=12
d=41, x=17, y=38
d=42, x=28, y=47
d=43, x=66, y=38
d=44, x=35, y= 8
d=45, x=45, y=60
d=46, x= 6, y=67
d=47, x=29, y=71
d=48, x=68, y=16
d=49, x=21, y= 5
d=50, x=75, y=38
d=51, x=19, y=54
d=52, x=63, y=16
d=53, x= 9, y=74
d=54, x=39, y=32
d=55, x=12, y=32
d=56, x=18, y=25
d=57, x=26, y=60
d=58, x=37, y=10
d=59, x=43, y=44
d=60, x=61, y=69
d=61, x=59, y=67
d=62, x=42, y=25
d=63, x=49, y=74
d=64, x=15, y=71
d=65, x=60, y=69
d=66, x= 1, y=61
d=67, x= 0, y= 0
d=68, x= 1, y=18
(1,18)+(0,0)=(1,18)
Ciekawostka od tłumacza: przykłady większych krzywych eliptycznych są w jednym z anglojęzycznych tematów: https://bitcointalksearch.org/topic/smaller-elliptic-curves-y2-x37-based-on-secp256k1-5459153
Teraz już mamy wszystko, czego potrzebujemy, aby dowiedzieć się, dlaczego nie możemy mnożyć dwóch kluczy publicznych przez siebie. Zapiszmy parę mnożeń na kluczach prywatnych i zamieńmy je na odpowiednie klucze publiczne, zgodnie z tabelą wyżej:
5* 7=35
11*13=35 (mod 67)
(60,10)*(15, 8)=(59,12)
(42,54)*(61,10)=( 8,19)
(18,54)*(39,47)=( 8,19)
d= 2, x=27, y=16
d= 3, x=19, y=54
d= 4, x= 1, y=18
d= 5, x=21, y=74
d= 6, x= 8, y=19
d= 7, x=63, y=16
d= 8, x=60, y=10
d= 9, x=68, y=63
d=10, x=41, y=44
d=11, x= 9, y=74
d=12, x=15, y= 8
d=13, x=29, y= 8
d=14, x=55, y=18
d=15, x=39, y=32
d=16, x=49, y= 5
d=17, x= 6, y=12
d=18, x=23, y=61
d=19, x=12, y=32
d=20, x=42, y=54
d=21, x=45, y=19
d=22, x=74, y=44
d=23, x=18, y=25
d=24, x=59, y=12
d=25, x=35, y=71
d=26, x=14, y=12
d=27, x=26, y=60
d=28, x=61, y=10
d=29, x=66, y=41
d=30, x=17, y=38
d=31, x=37, y=10
d=32, x=43, y=35
d=33, x=28, y=32
d=34, x=28, y=47
d=35, x=43, y=44
d=36, x=37, y=69
d=37, x=17, y=41
d=38, x=66, y=38
d=39, x=61, y=69
d=40, x=26, y=19
d=41, x=14, y=67
d=42, x=35, y= 8
d=43, x=59, y=67
d=44, x=18, y=54
d=45, x=74, y=35
d=46, x=45, y=60
d=47, x=42, y=25
d=48, x=12, y=47
d=49, x=23, y=18
d=50, x= 6, y=67
d=51, x=49, y=74
d=52, x=39, y=47
d=53, x=55, y=61
d=54, x=29, y=71
d=55, x=15, y=71
d=56, x= 9, y= 5
d=57, x=41, y=35
d=58, x=68, y=16
d=59, x=60, y=69
d=60, x=63, y=63
d=61, x= 8, y=60
d=62, x=21, y= 5
d=63, x= 1, y=61
d=64, x=19, y=25
d=65, x=27, y=63
d=66, x=75, y=38
d=67, x= 0, y= 0
d=68, x=75, y=41
5* 7=35
11*13=35 (mod 67)
(27,16)*(19,54)=( 8,19)
(21,74)*(63,16)=(43,44)
( 9,74)*(29, 8)=(43,44)
(42,54)*(61,10)=( 8,19)
(18,54)*(39,47)=( 8,19)
8*12=24
20*28=6
44*52=6