Додавання на еліптичних кривих


29

Додавання на еліптичних кривих

Відмова від відповідальності: це не справляє справедливості щодо багатої еліптичної кривої. Це багато спрощено. Оскільки еліптичні криві останнім часом отримали багато уваги засобів масової інформації в контексті шифрування, я хотів дати невелике розуміння того, як "обчислення" на еліптичній кривій насправді працює.

Вступ

Еліптичні криві - це сукупності точок (x,y)у площині форми y^2 = x^3+Ax+B. (Крім того, 4A^3+27B^2 ≠ 0щоб уникнути неприємних особливостей.) Ви можете розглянути ці криві в будь-якій галузі. Якщо ви використовуєте поле дійсних чисел, криві можна візуалізувати і виглядати так:

два приклади еліптичних кривих
Джерело

Особливість цих кривих полягає в тому, що вони мають вбудовану арифметичну операцію, яка є аналогом додавання. Можна додавати і віднімати точки, і ця операція є і асоціативною, і комутативною (абелева група).

Як працює додавання?

Примітка: додавання точок на еліптичних кривих не є інтуїтивно зрозумілим. Таке доповнення визначається таким, яким воно є, оскільки воно має певні приємні властивості. Це дивно, але це працює.

Оскільки еліптичні криві утворюють групу, існує адитивна ідентичність, що є еквівалентом 0. Тобто додавання 0до будь-якої точки результату не змінить. Ця аддитивна ідентичність є "точкою" нескінченності. Усі лінії на площині включають цю точку в нескінченність, тому додавання її не має ніякої різниці.

Скажімо, будь-яка задана лінія перетинає криву в трьох точках, яка може бути 0, і що сума цих трьох точок є 0. Маючи це на увазі, погляньте на це зображення.

еліптична крива додавання особливих випадків
Джерело

Тепер, природне питання, що таке P+Q? Ну, якщо P+Q+R = 0, тоді P+Q = -R(як варіант R'). Де -R? Саме тут R + (-R) = 0, який знаходиться на іншій стороні осі х від Rтак, щоб лінія , що проходить через них у вертикальному положенні , що перетинаються лише R, -Rі 0. Ви можете побачити це в першій частині цього зображення:

схема різних доповнень на еліптичних кривих Джерело

Ще одна річ, яку ви можете побачити на цих зображеннях, це те, що сума точки з самою собою означає, що лінія дотична до кривої.

Як знайти перетини ліній та еліптичних кривих

У випадку двох чітких моментів

Як правило, існує рівно один рядок через дві точки P=(x0,y0), Q=(x1,y1). Якщо припустити, що вона не вертикальна, і дві точки є різними, ми можемо записати це як y = m*x+q. Коли ми хочемо знайти точки перетину з еліптичною кривою, ми можемо просто записати

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

що є поліномом третього ступеня. Це, як правило, не так легко вирішити, але ми вже знаємо дві нулі цього многочлена: дві xкоординати x0, x1двох точок, які ми хочемо додати!

Таким чином ми визначаємо лінійні коефіцієнти (x-x0)і залишаємося (x-x1)з третім лінійним коефіцієнтом, корінь якого - xкоордината точки R. ( -Rтеж із-за симетрії. Зауважте, що якщо R = (x2,y2)тоді -R = (x2,-y2). Із -групи, це не векторіальний мінус.)

У разі додавання однієї точки Pдо себе

У цьому випадку ми повинні обчислити дотичну криву при P=(x0,y0). Ми можемо безпосередньо писати mі qз точки зору A,B,x0,y0:

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

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

Ми отримуємо рівняння y = m*x+qі можемо продовжувати так само, як у пункті вище.

Повне дерево справ

Це повний перелік способів вирішення всіх цих випадків:

Нехай P,Qбудуть точки на еліптичній кривій (включаючи точку "нескінченності" 0)

  • Якщо P = 0або Q = 0, то P+Q = Qабо P+Q = Pвідповідно
  • Інакше P ≠ 0і Q ≠ 0, так нехай P = (x0,y0)і Q = (x1,y1):
    • Якщо P = -Q(це означає x0 = x1і y0 = -y1), тоP+Q = 0
    • Інше P ≠ -Q
      • Якщо x0 = x1тоді ми маємо P=Qі обчислюємо дотичну (див. Розділ вище) для того, щоб отримати R. ПотімP+Q = P+P = 2P = -R
      • Інше: ми можемо побудувати лінію форми y = m*x+yчерез ці дві точки (див. Розділ вище) для того, щоб обчислити R. ПотімP+Q=-R

Кінцеві поля

Для цього завдання ми розглянемо лише поля розміру, pде pє простим (і через деякі деталі p ≠ 2, p ≠ 3). Це має ту перевагу, що ви можете просто розрахувати mod p. Арифметика в інших полях набагато складніша.

Це в цьому прикладі ми встановлюємо, p = 5і всі рівності тут є конгруентами 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

Виклик

Враховуючи параметри A,Bеліптичної кривої, основна характеристика поля pта дві точки P,Qеліптичної кривої повертають їх суму.

  • Можна припустити, що параметри A,Bнасправді описують еліптичну криву, це означає, що 4A^3+27B^2 ≠ 0.
  • Можна припустити, що P,Qнасправді є точки на еліптичній кривій або- 0точка.
  • Можна припустити, що p ≠ 2,3це просто.

Випробування

Я зробив (не дуже елегантну) реалізацію в MATLAB / Octave, яку ви можете використовувати для власних тестових випадків: ideone.com Я сподіваюся, що це правильно. Це принаймні відтворило кілька розрахунків, які я зробив вручну.

Зверніть увагу на тривіальні тестові випадки, які працюють для всіх кривих, які ми розглядаємо тут:

Додавання нуля: P+0 = P Додавання зворотного:(x,y) + (x,-y) = 0


За p = 7, A = 0, B = 5дві точки P = (3,2)і Q = (6,2)знаходяться на еліптичній кривій. Потім виконується наступне:

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

Усі точки на еліптичній кривій є (3,2),(5,2),(6,2),(3,5),(5,5),(6,5),0


Бо p = 13, A = 3, B = 8ми отримуємо

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

Бо p = 17, A = 2, B = 2і P=(5,1) ми отримуємо

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)

Якщо ви справді амбітні, візьміть

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

і спробуйте знайти натуральне число nтаке n*(x0,y0) = (x1,y1). Додаткову інформацію тут.

Додаток

Перш за все велике ДЯКУЄМО @ El'endiaStarman за перегляд та редагування мого проекту!

Чому еліптичні криві?

Добре, це може здатися якимсь довільним рівнянням, але це не так, це зовсім загально: ми зазвичай вважаємо ті геометричні "фігури" в проективній площині (саме звідси походить "нескінченність". Там ми вважаємо все однорідним поліноми третього ступеня. (Ті, які мають нижчий чи вищий ступінь, було б надто складно або просто тривіально розглянути.) Після застосування деяких обмежень для отримання бажаних властивостей, а також після дегомогенізації цих поліномів (проектування в одну з трьох афінних площин ) ми закінчуємо рівняннями на кшталтy^2+a*x*y+b*y = x^3+c*x^2+d*x+eЦе еліптична крива у довгій формі Вейерштрасса. Це в основному ті самі криві, що ми вважали, але просто дещо перекошені. Маючи лінійне перетворення координат, ви можете легко скласти з цього коротке рівняння Вейєрстраса. приклад , який досі зберігає всі цікаві властивості.

Чому ми виключили p=2,3?

Це пов'язано з тим, що для короткої форми Вейерштрасса нам потрібне обмеження 4A^3+27B^2 ≠ 0, щоб уникнути особливості (докладніше про це нижче). У полі властивості 2, яке ми маємо, 4 = 0і в полі характеристичної 3, яке ми маємо 27 = 0, це унеможливлює криві у короткій формі бурхливості для цих видів полів.

Що таке особливості?

Якщо рівняння 4A^3+27B^2=0має місце, у нас є особливості, такі як: Як ви бачите в цих точках, ви не можете знайти похідну і, отже, не дотичну, яка "вбиває" операцію. Ви можете подивитися рівняння y^2 = x^3абоy^2 = x^3-3*x+2

Чому їх взагалі називають еліптичними кривими ?

Причина полягає в тому, що рівняння такої форми спливають в еліптичних інтегралах, наприклад, те, що ви отримуєте, коли хочете зарахувати, наприклад, довжину дуги еліпса. Коротке слайд-шоу про походження назви.

Що вони мають відношення до криптографії?

Є способи обчислити nP = P+P+...+Pдуже ефективно. Це можна використати, наприклад, для обміну ключами Diffie Hellman . Модульну арифметику можна замінити додаванням на підгрупах кручення, це лише точки на кривій, які мають кінцевий порядок. (Це означає, що mP = 0для деяких m, що в основному є просто розрахунковим mod m).

Відповіді:


4

Pyth, 105 100 байт

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

Введення очікується як (p, A, P, Q), де Pі Qє двома точками форми (x, y)або, якщо вони є спеціальним 0пунктом, так само 0. Ви можете спробувати його онлайн тут . Два останні приклади показують, як 0працює спец .

Щоб зберегти кілька байт, я використовую лише mod pостаточну відповідь. Це означає, що він робить такі речі, як x0^pкілька разів, не роблячи модульної експоненції, тому це може бути дуже повільним.

Він працює, дотримуючись приблизно тієї ж логіки, що і ця функція Python:

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)

Це значною мірою залежить від того, що модульна мультиплікативна інверсія xдорівнює, x^(p-2) mod pякщо pє простим. Таким чином, ми можемо обчислити mнахил лінії, знайшовши модульний мультиплікативний зворотний знаменник і помноживши його на чисельник. Досить зручно. Функція Python повинна обчислювати великі проблеми трохи ефективніше через використання pow.

Я також використав ярлики, показані на цій сторінці у Вікіпедії . Це досить цікаво, що я в кінцевому підсумку використовую лише Aодин раз, і Bне зовсім.

Також просто для розваги:

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)

multi_nPФункція обчислює n*Pдля заданого цілого числа nі точки P. Він використовує рекурсивну стратегію, розділяючи її nна дві частини p2fі remainderтаке, p2f + remainder = nі це p2f = 2^k. Потім знову викликаємо функцію в тих частинах, додаючи результат за допомогою add_ellip. Я також використовував базовий підхід до динамічного програмування, зберігаючи вже обчислені значення у dict d.

Наступна функція теоретично вирішила б бонусне питання, використовуючи ту саму стратегію:

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

На жаль, він не працює досить швидко, щоб обчислити його. Я здогадуюсь, що можуть бути набагато ефективніші способи зробити це, особливо якщо нам не доведеться повторювати кожне можливе значення n.


Чудово, я, чесно кажучи, більше не очікував жодних передвижників =) Як ти розбираєшся в нескінченності? (Зауважте, що y^2 = x^3 + xце дійсна еліптична крива і (0,0) ≠ 0є крапкою на кривій!)
недолік

Чудове запитання ... Я думаю, я не впорався! : P Мої вибачення, я пам'ятаю, як побачив першу картину, де B = 0і цікавився, як 0би це працювало ... а потім забув про це. Я думаю, що я припустив, що Bне може бути 0 у якийсь момент пізно вчора ввечері. Чи є у вас які-небудь пропозиції щодо того, який вклад повинен бути для цього? Можливо, якщо B = 0, то визначте 0 = (-1, -1)? Я радий налаштувати свій код, щоб обробити його, я просто думаю, що було б добре, якщо він також буде стандартизований і для інших подань ...
Rhyzomatic

Ну і я залишив цей понт відкритим, щоб подані матеріали могли використовувати те, що їм зручно. Але, звичайно, можна сказати, що, наприклад, всі кінцеві точки на кривій мають неотримані координати, а все інше розглядається як точка нескінченності чи щось подібне. Або якщо це простіше, ви також можете припустити, що вхід [0](лише одна координата) - це точка нескінченності, або щось подібне!
flawr

Дайте мені знати, якщо це не справляється з цим досить добре. І дякую, що насправді врятувало мене 5 байт!
Різоматик

@flawr, чи зможете ви сказати мені, чи я на правильному шляху ефективного обчислення nP? Не могли б ви вказати мені на якісь ресурси з цього питання, щоб думки випливали? Мені важко знайти щось гуглінг навколо. Спасибі!
Різоматик

0

Пітон 3, 193 191 байт

Рішення, засноване на Pyth відповіді Rhyzomatic та їх логіці Python. Зокрема. Мені сподобалося, як вони знайшли третій корінь монічного кубічного многочлена, x^3 + bx^2 + cx + dколи у вас є два корені, x_1і x_2помітивши це b == x_1 + x_2 + x_3та віднімаючи відповідно. Я планую додати пояснення, гольфувати це, і, можливо, перетворити його на Ruby, якщо Ruby виявиться коротшим.

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)

Ungolfing:

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)

Я здивований, що Python менш ніж удвічі довший, ніж відповідь Pyth!
flawr
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.