시작하기에 앞서, Baby-step Giant-step Algorithm(BSGS Algorithm)을 이해하기 위해 필요한 이산 로그 문제(Discrete Logarithm Problem, DLP)에 대해 간단히 설명하겠다.
일반적으로 양의 실수 집합에서 정의되는 로그(Logarithm)는
BSGS Algorithm은 위와 같은
이상 미만인 모든 정수 에 대해 를 집합 에 삽입한다. (Baby-step) 이상 미만인 모든 정수 에 대해 를 계산하고, 이 값이 에 있는지 확인한다. 있다면 를 만족하는 를 찾는다. (Giant-step) 를 결과로써 반환한다.
BSGS Algorithm의 정당성 증명
임의의
2.에서
이 식의 양변에
BSGS Algorithm의 시간복잡도 증명
분할정복을 이용해 거듭제곱을 계산하면
따라서 1.에서는
2.에서는 거듭제곱과 모듈로 역원을 한 번 계산하고 집합에의 포함 여부를 판별하는데 각각
결론적으로 BSGS Algorithm은
BSGS Algorithm의 구현
이산 로그를 구현한 대부분의 잘 알려진 구현체는 BSGS보다 빠른 시간에 동작하는 pollard-rho algorithm, 혹은 pohlig-hellman algorithm 등을 구현한다. 따라서 이들을 사용 가능하다면 사용하기를 권장한다. 아래는 C++로 구현된 BSGS algorithm이다.
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
ll ipow(ll x,ll n,ll p){
if(n==0)return 1;
if(n==1)return x%p;
if(n==2)return (x%p)*(x%p)%p;
ll k=ipow(x*x%p,n/2,p);
if(n%2==1)k=k*x%p;
return k;
}
ll discrete_log(ll n,ll b,ll p){
set<ll> s;
ll k=ceil(sqrt(p));
ll binvk=ipow(ipow(b,k,p),p-2,p);//by fermat's little theorem
ll t;
//baby-step
t=1;
for(ll i=0;i<k;i++){
s.insert(t);
t*=b;
t%=p;
}
//giant-step
t=1;
for(ll i=0;i<k;i++){
ll x=n*t%p;
if(s.find(x)!=s.end()){
t=1;
for(ll j=0;j<k;j++){
if(t==x){
return i*k+j;
}
t*=b;
t%=p;
}
}
t*=binvk;
t%=p;
}
return -1;
}
'ctf' 카테고리의 다른 글
Whitehat Contest 2022 본선 Crypto writeup (0) | 2022.12.04 |
---|---|
2022 Fall GoN Open Qual CTF Write-up (1) | 2022.08.28 |
HackTheon 2022 Writeup (0) | 2022.08.11 |
Introduction and Proof of Tonelli-Shanks Algorithm (2) | 2022.08.03 |
CTF 암호학을 위한 기초적 확률 지식 / Basic Knowledge about Probability for CTF (1) | 2022.06.11 |