Tambahan pada Kurva Elliptic

29

Tambahan pada Kurva Elliptic

Penafian: Ini tidak adil pada topik kaya kurva elips. Ini banyak disederhanakan. Karena kurva eliptik baru-baru ini mendapat banyak perhatian media dalam konteks enkripsi, saya ingin memberikan beberapa wawasan kecil bagaimana "menghitung" pada kurva eliptik benar-benar berfungsi.

pengantar

Kurva berbentuk bulat panjang adalah set poin (x,y)di bidang bentuk y^2 = x^3+Ax+B. (Selain itu, 4A^3+27B^2 ≠ 0untuk menghindari singularitas buruk.) Anda dapat mempertimbangkan kurva ini di bidang apa pun. Jika Anda menggunakan bidang bilangan real, kurva dapat divisualisasikan dan terlihat seperti ini:

dua contoh kurva eliptik
Sumber

Hal khusus tentang kurva ini adalah bahwa mereka telah sebuah dibangun di operasi aritmatika yang merupakan analog dari penambahan. Anda dapat menambah dan mengurangi poin, dan operasi ini bersifat asosiatif dan komutatif (grup abelian).

Bagaimana cara kerja penambahan?

Catatan: penambahan titik pada kurva elips tidak intuitif. Penambahan semacam ini didefinisikan sebagaimana adanya karena memiliki sifat-sifat bagus tertentu. Aneh, tapi berhasil.

Sebagai kurva eliptik membentuk grup, ada identitas aditif yang setara dengan 0. Artinya, menambahkan 0titik apa pun tidak akan mengubah hasilnya. Identitas aditif ini adalah "titik" di infinity. Semua garis di pesawat termasuk titik ini hingga tak terbatas, jadi menambahkannya tidak ada bedanya.

Katakanlah setiap garis memotong kurva pada tiga titik, yang mungkin 0, dan bahwa jumlah dari ketiga titik ini adalah 0. Ingatlah itu, lihat gambar ini.

kurva khusus elips ditambah kasus khusus
Sumber

Sekarang, pertanyaan alami adalah, apa itu P+Q? Nah, jika P+Q+R = 0, lalu P+Q = -R(atau ditulis sebagai R'). Dimana -R? Ini adalah di mana R + (-R) = 0, yang di sisi lain dari sumbu x dari Rsehingga garis melalui mereka adalah vertikal, berpotongan hanya R, -R, dan 0. Anda dapat melihat ini di bagian pertama gambar ini:

diagram berbagai penambahan pada kurva elips Sumber

Hal lain yang dapat Anda lihat dalam gambar-gambar ini adalah jumlah titik dengan dirinya sendiri berarti garis bersinggungan dengan kurva.

Cara menemukan persimpangan garis dan kurva eliptik

Dalam hal dua titik berbeda

Umumnya hanya ada satu garis melalui dua titik P=(x0,y0), Q=(x1,y1). Dengan asumsi itu tidak vertikal dan dua titik berbeda, kita dapat menuliskannya sebagai y = m*x+q. Ketika kita ingin menemukan titik-titik persimpangan dengan kurva elips kita bisa menulis

0 = x^3+Ax+B-y^2 = x^3+Ax+B-(m*x+q)^2

yang merupakan polinomial tingkat ketiga. Ini umumnya tidak mudah untuk dipecahkan, tetapi kita sudah tahu dua nol dari polinomial ini: Dua- xkoordinat x0, x1dari dua poin yang ingin kita tambahkan!

Dengan begitu kita memfaktorkan faktor-faktor linier (x-x0)dan (x-x1)dan dibiarkan dengan faktor linier ketiga yang akarnya adalah x-koordinat titik R. ( -Rjuga karena simetri. Perhatikan bahwa jika R = (x2,y2)demikian -R = (x2,-y2). Ini -dari grup; itu bukan minus vektorial.)

Dalam hal menambahkan satu titik Pke dirinya sendiri

Dalam hal ini kita harus menghitung garis singgung kurva pada P=(x0,y0). Kami dapat langsung menulis mdan qdalam hal A,B,x0,y0:

     3*x0^2 + A
m = ------------
        2*y0

     -x0^3 + A*x0 + 2*B
q = --------------------
          2*y0

Kami mendapatkan persamaan y = m*x+qdan dapat melanjutkan dengan cara yang sama seperti pada paragraf di atas.

Pohon kasus lengkap

Ini adalah daftar lengkap cara menangani semua kasus tersebut:

Membiarkan P,Qmenjadi poin pada kurva elips (termasuk titik "tak terbatas" 0)

  • Jika P = 0atau Q = 0, kemudian P+Q = Qatau P+Q = P, masing-masing
  • Lain P ≠ 0dan Q ≠ 0, jadi biarkan P = (x0,y0)dan Q = (x1,y1):
    • Jika P = -Q(artinya x0 = x1dan y0 = -y1) makaP+Q = 0
    • Lain P ≠ -Q
      • Jika x0 = x1kemudian kita miliki P=Qdan kita menghitung garis singgung (lihat bagian di atas) untuk mendapatkan R. KemudianP+Q = P+P = 2P = -R
      • Lain: Kita dapat membuat garis formulir y = m*x+ymelalui dua titik (lihat bagian di atas) untuk menghitung R. KemudianP+Q=-R

Bidang terbatas

Untuk tantangan ini, kami hanya akan mempertimbangkan bidang ukuran di pmana pprima (dan karena beberapa detail p ≠ 2, p ≠ 3). Ini memiliki keuntungan yang bisa Anda hitung dengan mudah mod p. Aritmatika di bidang lain jauh lebih rumit.

Ini dalam contoh ini kita atur p = 5dan semua persamaan di sini adalah kongruensi mod 5.

2+4 ≡ 6 ≡ 1
2-4 ≡ -2 ≡ 3
2*4 ≡ 8 ≡ 3
2/4 ≡ 2*4 ≡ 3 because 4*4 ≡ 16 ≡ 1, therefore 1/4 ≡ 4

Tantangan

Dengan parameter A,Bkurva eliptik, karakteristik bidang utama, pdan dua titik P,Qpada kurva eliptik, kembalikan jumlahnya.

  • Anda dapat mengasumsikan bahwa parameter A,Bsebenarnya menggambarkan kurva elips, itu artinya 4A^3+27B^2 ≠ 0.
  • Anda dapat mengasumsikan bahwa P,Qsebenarnya adalah titik pada kurva eliptik atau 0-poin.
  • Anda dapat menganggap itu p ≠ 2,3prima.

Uji Kasus

Saya membuat implementasi (tidak terlalu elegan) di MATLAB / Octave, yang dapat Anda gunakan untuk kasus uji Anda sendiri: ideone.com Saya harap itu benar. Setidaknya itu mereproduksi beberapa perhitungan yang saya buat dengan tangan.

Perhatikan kasus uji sepele yang bekerja untuk semua kurva yang kami pertimbangkan di sini:

Menambahkan nol: P+0 = P Menambahkan invers:(x,y) + (x,-y) = 0


Untuk p = 7, A = 0, B = 5dua titik P = (3,2)dan Q = (6,2)berada pada kurva elips. Kemudian memegang berikut:

2*Q = Q+Q = P
2*P = P+P = (5,2)
3*P = P+P+P = (5,2)+P = (6,5)
4*P = P+P+P+P = (5,2)+(5,2) = (6,5)+(5,2) = Q

Semua poins pada kurva elips adalah (3,2),(5,2),(6,2),(3,5),(5,5),(6,5),0


Untuk p = 13, A = 3, B = 8kita dapatkan

(1,8)+(9,7) = (2,10)
(2,3)+(12,11) = (9,7)
2*(9,6) = (9,7)
3*(9,6) = 0

Untuk p = 17, A = 2, B = 2dan P=(5,1) kita dapatkan

2*P = (6,3)
3*P = (10,6)
4*P = (3,1)
5*P = (9,16)
6*P = (16,13)
7*P = (0,6)
8*P = (13,7)
9*P = (7,6)
10*P = (7,11)

Jika Anda benar-benar ambisius, ambillah

p = 1550031797834347859248576414813139942411
A = 1009296542191532464076260367525816293976
x0 = 1317953763239595888465524145589872695690
y0 = 434829348619031278460656303481105428081
x1 = 1247392211317907151303247721489640699240
y1 = 207534858442090452193999571026315995117

dan mencoba mencari nomor alami nsedemikian rupa n*(x0,y0) = (x1,y1). Informasi lebih lanjut di sini.

Lampiran

Pertama-tama, terima kasih banyak kepada @ El'endiaStarman untuk meninjau dan mengedit konsep saya!

Mengapa kurva elips?

Yah itu mungkin tampak seperti semacam persamaan arbitrer, tetapi tidak, itu cukup umum: Secara umum kita menganggap "bentuk" geometris di bidang proyektif (di situlah "infinity" berasal. Di sana kita menganggap semua homogen polinomial tingkat tiga. (Yang lebih rendah atau lebih tinggi akan terlalu sulit atau hanya sepele untuk diperiksa.) Setelah menerapkan beberapa batasan untuk mendapatkan properti bagus yang kita inginkan, dan setelah melakukan dehomogenisasi polinomial tersebut (memproyeksikan ke salah satu dari tiga pesawat affine ) kita berakhir dengan persamaan sepertiy^2+a*x*y+b*y = x^3+c*x^2+d*x+eIni adalah kurva elips dalam bentuk Weierstrass yang panjang. Ini pada dasarnya adalah kurva yang sama seperti yang kami pertimbangkan, tetapi hanya agak miring. Dengan transformasi koordinat linier, Anda dapat dengan mudah membuat persamaan Weierstras pendek dari itu. contoh , yang masih menyimpan semua properti menarik.

Mengapa kami mengecualikan p=2,3?

Ini ada hubungannya dengan fakta bahwa untuk bentuk Weierstrass pendek kita perlu pembatasan 4A^3+27B^2 ≠ 0untuk menghindari singularitas (lebih lanjut tentang itu di bawah). Dalam bidang karakteristik 2 yang kita miliki 4 = 0dan dalam bidang karakteristik 3 yang kita miliki 27 = 0, ini tidak memungkinkan untuk memiliki kurva dalam bentuk kelas pendek untuk jenis bidang tersebut.

Apa itu singularitas?

Jika persamaan tersebut 4A^3+27B^2=0berlaku, kita memiliki singularitas seperti berikut: Seperti yang Anda lihat pada titik-titik itu Anda tidak dapat menemukan turunan dan karenanya tidak bersinggungan, yang "membunuh" operasi. Anda mungkin melihat persamaan y^2 = x^3atauy^2 = x^3-3*x+2

Mengapa mereka disebut kurva eliptik ?

Alasannya adalah bahwa persamaan bentuk ini muncul di integral elips, misalnya yang Anda dapatkan ketika Anda ingin mengkombinasikan misalnya panjang gelombang dari sebuah elips. Tayangan slide singkat tentang asal usul nama.

Apa yang harus mereka lakukan dengan kriptografi?

Ada cara untuk menghitung dengan nP = P+P+...+Psangat efisien. Ini dapat digunakan misalnya dalam pertukaran kunci Diffie Hellman . Aritmatika modular dapat diganti dengan penambahan pada subkelompok torsi, ini hanya titik-titik pada kurva yang memiliki urutan terbatas. (Itu artinya mP = 0bagi sebagian orang m, yang pada dasarnya hanya menghitung mod m).

cacat
sumber

Jawaban:

4

Pyth, 105 100 byte

A,@Q3eQ?qGZH?qHZG?&=YqhHhGqeG%_eHhQZ_m%dhQ,-*J?Y*+*3^hG2@Q1^*2eG-hQ2*-eGeH^-hGhH-hQ2-hGK--^J2hGhHeGK

Input diharapkan sebagai (p, A, P, Q), di mana Pdan Qmerupakan dua titik dari formulir (x, y)atau, jika mereka adalah 0titik khusus , sama seperti 0. Anda dapat mencobanya online di sini . Dua contoh terakhir menunjukkan cara kerja khusus 0.

Untuk menghemat beberapa byte, saya hanya menggunakan mod pjawaban akhir. Ini berarti bahwa ia melakukan hal-hal seperti x0^pbeberapa kali tanpa melakukan eksponensial modular, sehingga mungkin sangat lambat.

Ia bekerja dengan mengikuti kira-kira logika yang sama dengan fungsi Python ini:

def add_ellip(p, A, P, Q): # points are in format (x, y)
    z = 0 # representing special 0 point

    if (P == z):
        return Q
    if (Q == z):
        return P

    if P[0] == Q[0]:
        if (P == (Q[0], -Q[1] % p)):
            return z
        else:
            m = ((3*pow(P[0], 2, p) + A)*pow(2*P[1], p-2, p)) % p
    else:
        m = (P[1] - Q[1])*pow(P[0] - Q[0], p-2, p) % p

    x = (pow(m, 2, p) - P[0] - Q[0]) % p
    y = (m*(P[0] - x) - P[1]) % p
    return (x, y)

Ini sangat bergantung pada fakta bahwa invers multiplikatif modular xsama dengan x^(p-2) mod pif padalah prima. Dengan demikian kita dapat menghitung m, kemiringan garis, dengan menemukan inversi multiplikatif modular dari penyebut dan mengalikannya dengan pembilang. Cukup berguna. Fungsi Python harus menghitung masalah yang lebih besar sedikit lebih efisien karena penggunaan pow.

Saya juga menggunakan cara pintas yang diperlihatkan di halaman Wikipedia tentang hal ini . Cukup menarik. Saya hanya menggunakan Asekali saja, dan Btidak sama sekali.

Juga hanya untuk bersenang-senang:

def pow2floor(x):
    p = 1
    x >>= 1
    while (x > 0):
        x >>= 1
        p <<= 1
    return p

def multi_nP(p, A, n, P):
    d = {}

    def rec_helper(n, P):
        if (n == 0):
            return (0, 0)
        elif (n == 1):
            return P
        elif (n in d):
            return d[n]
        else:
            p2f = pow2floor(n)
            remainder = n - p2f

            lower_half = rec_helper(p2f//2, P)
            d[p2f//2] = lower_half
            nP = add_ellip(p, A, lower_half, lower_half)

            if (remainder):
                nP = add_ellip(p, A, nP, rec_helper(remainder, P))

            d[n] = nP
            return nP

    return rec_helper(n, P)

The multi_nPfungsi menghitung n*Puntuk bilangan bulat tertentu ndan titik P. Ia menggunakan strategi rekursif dengan memecah nmenjadi dua bagian p2fdan remainderseperti itu p2f + remainder = ndan itu p2f = 2^k. Kemudian kita memanggil fungsi lagi di bagian-bagian itu, menambahkan hasilnya dengan add_ellip. Saya juga menggunakan pendekatan pemrograman dinamis dasar dengan menyimpan nilai yang sudah dihitung di dikt d.

Fungsi selanjutnya secara teoritis akan memecahkan pertanyaan bonus menggunakan strategi yang sama:

def find_nPQ(p, A, P, Q): # P is input point, Q is what we're looking for
    d = {}
    found_Q = False

    def rec_helper(n, P):
        if (n == 0):
            return (0, 0)
        elif (n == 1):
            return P
        elif (n in d):
            return d[n]
        else:
            p2f = pow2floor(n)
            remainder = n - p2f

            lower_half = rec_helper(p2f//2, P)
            d[p2f//2] = lower_half

            nP = add_ellip(p, A, lower_half, lower_half)

            if (remainder):
                nP = add_ellip(p, A, nP, rec_helper(remainder, P))

            d[n] = nP
            return nP


    for x in range(p):
        xP = rec_helper(x, P)
        if (xP == Q):
            return x

Sayangnya, itu berjalan cukup cepat untuk menghitungnya. Saya menduga mungkin ada banyak cara yang lebih efisien untuk melakukan ini, terutama jika kita tidak perlu mengulangi setiap nilai yang mungkin ada n.

Berirama
sumber
Hebat, saya sejujurnya tidak mengharapkan jawaban lagi =) Bagaimana Anda menangani masalah ini tanpa batas? (Perhatikan bahwa itu y^2 = x^3 + xadalah kurva elips yang valid dan (0,0) ≠ 0merupakan titik pada kurva!)
flawr
Pertanyaan bagus ... Saya kira saya tidak menanganinya! : P Permintaan maaf saya, saya ingat melihat gambar pertama di mana B = 0dan bertanya-tanya bagaimana cara 0kerjanya ... dan kemudian saya melupakannya. Saya pikir saya berasumsi Btidak mungkin menjadi 0 di beberapa titik tadi malam. Apakah Anda memiliki saran tentang apa yang harus input untuk ini? Mungkin jika B = 0, lalu definisikan 0 = (-1, -1)? Saya senang menyesuaikan kode saya untuk menanganinya, saya hanya berpikir akan lebih baik jika standar untuk kiriman lainnya juga ...
Rhyzomatic
Yah saya meninggalkan pont terbuka sehingga pengiriman bisa menggunakan apa pun yang nyaman bagi mereka. Tetapi tentu saja Anda dapat mengatakan bahwa misalnya semua titik hingga pada kurva memiliki koordinat tidak negatif, dan segala sesuatu yang lain dianggap sebagai titik Infinity atau sesuatu yang serupa. Atau jika lebih mudah Anda juga bisa berasumsi bahwa input[0] (hanya satu koordinat) adalah titik tak terhingga, atau yang serupa!
flawr
Beri tahu saya jika itu tidak cukup baik. Dan terima kasih, itu benar-benar menyelamatkan saya 5 byte!
Rhyzomatic
@ flawr, bisakah Anda memberi tahu saya jika saya berada di jalur yang benar untuk komputasi yang efisien nP? Bisakah Anda mengarahkan saya ke sumber daya apa pun pada subjek untuk mendapatkan pemikiran mengalir? Saya kesulitan menemukan apa pun yang dicari Google. Terima kasih!
Rhyzomatic
0

Python 3, 193 191 byte

Sebuah solusi berdasarkan jawaban Pyth Rhyzomatic dan logika Python mereka. Khususnya. Saya suka bagaimana mereka menemukan akar ketiga polinomial kubik monic x^3 + bx^2 + cx + dketika Anda memiliki dua akar x_1dan x_2dengan mencatat itu b == x_1 + x_2 + x_3dan mengurangi sesuai. Saya berencana untuk menambahkan penjelasan, mainkan ini, dan mungkin mengubahnya menjadi Ruby, jika ternyata Ruby lebih pendek.

def e(p,A,B,P,Q):
 if P==0:return Q
 if Q==0:return P
 f,g=P;j,k=Q
 if f==j:
  if g==-k%p:return 0
  m=(3*f*f+A)*pow(2*j,p-2)
 else:m=(g-k)*pow(f-j,p-2)
 x=m*m-f-j;y=m*(f-x)-g;return(x%p,y%p)

Tidak melakukan pelanggaran:

def elliptic_curve_addition(p, A, B, P, Q):
    if P == 0:
        return Q
    if Q == 0:
        return P
    f,q = P
    j,k = Q
    if f==j:
        if g == (-k) % p:
            return 0
        m = (3 * f**2 + A) * pow(2*j, p-2)
    else:
        m = (g-k) * pow(f-j, p-2)
    x = m**2 - f - j
    y = m * (f-x) - g
    return (x%p, y%p)
Sherlock9
sumber
Saya terkejut bahwa Python kurang dari dua kali lipat jawaban Pyth!
flawr