[CryptoHack] Extended GCD

거대한리트리버·2023년 8월 18일
0
post-thumbnail

문제

풀이

확장 유클리드 알고리즘을 사용하여 구한 u, v 중 작은 것이 flag이다.
우선 확장 유클리드 알고리즘을 이해하기 위해서는 베주 항등식에 대해 알고 있어야 한다.

베주 항등식(Bézout's Identity)

정수 a,b(적어도 둘 중 하나는 0이 아님)의 최대공약수를 d라고 할 때,
ax + by = d를 만족하는 정수 x,y가 반드시 존재한다.
+)정수 x,y에 대해 ax + by 꼴로 표현되는 모든 정수는 d의 배수이다.

확장 유클리드 알고리즘(Extended Euclidean Algorithm)

베주 항등식에 의해 gcd(a,b)=dgcd(a,b) = d라고 할 때, ax+by=dax + by = d를 만족하는
정수 x,yx,y가 존재하며 이는 유클리드 알고리즘의 과정을 역으로 계산하면 알 수 있다.

우선 유클리드 알고리즘의 과정을 식으로 표현하면 다음과 같다.

a=bq0  +  r1b=r1q1  +  r2r1=r2q2  +  r3...ri1=riqi  +  ri+1a = bq_0 \;+\;r_1 \\b = r_1q_1\;+\;r_2\\r_1 = r_2q_2\;+\;r_3\\...\\r_{i-1}=r_iq_i\;+\;r_{i+1}

여기서 ri+1=ri1riqir_{i+1}=r_{i-1}-r_iq_i라는 식을 도출해낼 수 있다.

알고리즘의 종료 조건은 나머지가 0이 될 때이므로 ri+1=0r_{i+1}=0을 만족하는 시점이다.
그리고 d는 rir_i이므로 d=ax  +  byd=ax\;+\;by 꼴로 나타내기 위해 r0=ar_0=a, r1=br_1=b라고 하면
r0=a    1  +  b    0r_0=a\;*\;1\;+\;b\;*\;0 이고 r1=a    0  +  b    1r_1=a\;*\;0\;+\;b\;*\;1 라고 할 수 있다.

이후 rir_i들도 같은 꼴로 나타내어지기 때문에 aa의 계수를 sis_i, bb의 계수를 tit_i라고 할 때
ri  =  sia  +  tibr_i\;=\;s_ia\;+\;t_ib라는 식을 얻을 수 있다.

위 식을 ri+1=ri1riqir_{i+1}=r_{i-1}-r_iq_irr에 모두 대입해주면 다음과 같은 점화식을 얻을 수 있다.

si+1a  +  ti+1b  =  (si1a  +  ti1b)    (sia  +  tib)qi=si1a    siaqi  +  ti1b    tibqi=(si1    siqi)a  +  (ti1    tiqi)bs_{i+1}a\;+\;t_{i+1}b\;=\;(s_{i-1}a\;+\;t_{i-1}b)\;-\;(s_ia\;+\;t_ib)q_i\\=s_{i-1}a\;-\;s_iaq_i\;+\;t_{i-1}b\;-\;t_ibq_i\\=(s_{i-1}\;-\;s_iq_i)a\;+\;(t_{i-1}\;-\;t_iq_i)b

계수 비교를 통해 최종적으로 다음 식들을 얻을 수 있다.

r0  =  a,  r1  =  bs0  =  1,  s1  =  0t0  =  0,  t1  =  1ri+1  =  ri1riqisi+1  =  si1siqiti+1  =  ti1tiqir_0\;=\;a,\;r_1\;=\;b\\s_0\;=\;1,\;s_1\;=\;0\\t_0\;=\;0,\;t_1\;=\;1 \\r_{i+1}\;=\;r_{i-1}-r_iq_i\\s_{i+1}\;=\;s_{i-1}-s_iq_i\\t_{i+1}\;=\;t_{i-1}-t_iq_i\\

이제 이 식들을 구현해주자.

def EEA(a,b):
    r_0 = a; r_1 = b; s_0 = 1; t_0 = 0; s_1 = 0; t_1 = 1; q = 0; temp = 0

    while(r_1):
        q = r_0 // r_1
        temp = r_0
        r_0 = r_1
        r_1 = temp - r_0 * q
        temp = s_0
        s_0 = s_1
        s_1 = temp - s_0 * q
        temp = t_0
        t_0 = t_1
        t_1 = temp - t_0 * q
        print("%d = %d * %d + %d, %d, %d" %(r_0 * q + r_1, r_0, q, r_1, s_1, t_1))

EEA(32321,26513)

점화식 꼴이기 때문에 temp 변수를 사용하여 i를 1씩 늘려주며 계산하는 방식의 코드이다.

가장 마지막의 sis_itit_i값이 bba-a꼴로 나오는 것까지 확인할 수 있다.

FLAG = -8404

profile
강아지귀여워

0개의 댓글