본 글에서는 MEGA의 취약점에 대해 다룬 논문(이하 2번 논문)을 소개합니다. 해당 논문은 MEGA: Malleable Encryption Goes Awry(이하 1번 논문)서 소개된 attack surface에서 정보를 더 효율적으로 추출하는 방법을 제안합니다.
간략히 설명하자면, 1번 논문에서는 RSA private key가 AES ECB mode로 암호화되었다는 사실을 이용하여 클라이언트의 로그인 시도가 임의의 수와 RSA public moduli $N$의 더 작은 소인수 간의 크기 비교가 가능한 oracle이 될 수 있음을 활용합니다. 이를 통해 512번 내지는 1024번의 로그인 시도가 축적되면 서버가 유저의 RSA private key를 알 수 있다는 점을 다루고 있습니다.
2번 논문에서는 유저가 challenge에 응답하는 과정에서 송신하는 정보의 양이 1번 논문의 공격자가 얻는 정보의 양보다 훨씬 많다는 점에 주목합니다. 다른 방식으로 다른 정보를 얻는 oracle과 payload를 구성하고, 적게는 6번에서 많게는 17번 정도의 로그인 시도만으로 유저의 RSA private key를 복구합니다.
MEGA의 구성
우선 공격 대상인 MEGA에서 프로토콜이 어떻게 구성되는지를 살펴보겠습니다. 공격 내용 설명의 편의를 위해 실제와는 다소 다를 수 있습니다.
[유저 생성 시]
각 유저에 대해 다음의 정보가 생성됩니다. 이는 로그인 시 변하지 않는 불변값입니다.
- master key (16byte) : AES Encryption을 위한 키입니다. MEGA에서는 ECB mode로만 AES를 활용하기에 iv값은 필요하지 않습니다.
- shared key : RSA2048 private key를 생성합니다. 구성은 다음과 같습니다.
- $p,q$ : public moduli $N$의 서로 다른 두 소인수입니다. 각각 1024비트의 소수입니다.
- $d$ : secret exponent입니다. public exponent $e$에 대해 $ed\mod \phi(N) = 1$을 만족합니다.
- $u$ : $u\text{:=}q^{-1}\mod p$로 정의되는 값입니다. 연산속도 향상을 위한 CRT-RSA에서 사용되는 값으로써 저장되어있습니다
참고로, MEGA의 웹 클라이언트에서는 public exponent $e$로 257을 사용합니다. 흔히 채택되는 65537과 비교하여 비트 길이 기준 절반 정도의 작은 크기입니다.
해당 정보를 생성한 후 shared key는 master key를 이용하여 AES ECB mode 암호화한 결과값 $ct$가 서버에 저장됩니다. 구체적으로는, RSA private key가 암호화 이전 다음과 같이 인코딩됩니다.
$$sk_{\text{share}}^{\text{encoded}} = l(q)\Vert q\Vert l(p)\Vert p\Vert l(d)\Vert d\Vert l(u)\Vert u\Vert P$$
$l(x)$는 $x$의 비트 길이를 의미하는 2바이트 값, $p,q,d,u$는 상기된 RSA private key이며 $P$는 16byte alignment를 맞추기 위한 패딩입니다. 여기서, 이전 데이터들의 총 길이가 648바이트이므로 패딩 $P$는 8바이트로 구성됩니다.
[유저 로그인 시]
유저의 로그인 시도가 발생할 시 서버는 다음과 같은 challenge $C$를 구성하여 유저에게 전송합니다. 마지막 SID의 추출에서 $m$은 256바이트로 패딩된 상태의 바이트열입니다.
$$C\text{:=}(SID_{\text{enc}},ct)$$
유저는 $C$를 수신한 후, 다음과 같은 계산 과정을 거쳐 $SID$를 구하고 이를 회신합니다.
$$\begin{align}m_p &\text{ := } c^{d\text{ mod }(p-1)}\text{ mod } p\\m_q &\text{ := } c^{d\text{ mod }(q-1)}\text{ mod } q\\m &\text{ := } ((m_p-m_q)u \text{ mod } p)q +m_q\\SID &\text{ := } m[2:44]\end{align}$$
서버는 해당 값이 $SID^e\text{ mod }N = SID_{\text{enc}}$를 만족하는지 확인하는지 확인합니다.
Malleable Encryption Goes Awry (1번 논문)
서술의 편의를 위해 $r\text{ := }\min\{p,q\}$라고 정의하겠습니다. CRT-RSA decryption의 마지막 계산식인
$$m \text{ := } ((m_p-m_q)u \text{ mod } p)q +m_q$$
에서 $m_p-m_q\neq 0$, 즉 $m_p \neq m_q$일 조건은 $m\ge r$입니다.
이때, 우리는 이 식을 계산할 때 사용되는 $p,q,d,u$가 서버가 제공하는 암호화된 shared key의 값에 의존적임을 상기해봅시다. 이는 즉 서버의 입장에서 암호화된 shared key를 다른 값으로 바꾸어도 이를 막는 장치가 없음을 의미합니다.
물론 이것이 암호화된 채로 서버에 저장되어있어 서버가 원하는 값으로 바꾸는 것은 불가능합니다만, 값을 바꾸는 것 자체는 가능합니다. 가령 40번 블럭을 랜덤으로 바꾸는 것이 이에 해당합니다.
위 내용을 기억하며, 서버가 challenge $({x}^e \text{ mod }N, ct^\prime)$을 보냈을 때를 생각해봅시다. 이때 $x$는 0 이상 $N$ 미만의 임의의 정수이며, $ct^\prime$은 $ct$의 40번 블럭을 임의의 값으로 변경한 암호화된 shared key입니다.
유저는 우선 $ct^\prime$을 복호화하여 조작된 shared key $(p,q,d,u^\prime)$을 획득합니다. 40번 블럭만이 변경되었으므로 $p,q,d$의 값은 변동이 없으며, $u^\prime$의 값은 서버가 알지 못함에 유의합시다.
유저는 아래 식을 이용하여 $m^\prime$을 계산합니다.
$$m^\prime \text{ := } ((m_p-m_q)u^\prime \text{ mod } p)q +m_q$$
여기서, $x$의 크기를 기준으로 경우를 나눠봅시다.
[ 1. $x<r$ ]
$m_p=m_q$이므로 $m^\prime = m_q$입니다. $m_q<q$이므로 $m^\prime$은 1024비트 이하의 값입니다.
따라서 $m^\prime$의 값은 패딩에 해당하는 후반 128바이트 내에 위치하며, $SID \text{ := } m[2:44]$에서 모두 truncate되어 결론적으로 $SID=0$이 도출됩니다.
[2. $x\ge r$]
$m_p=m_q$이므로 $m^\prime = ((m_p-m_q)u^\prime \text{ mod } p)q +m_q$입니다.
$m_p$는 높은 확률로 1024비트 이상의 값이므로, $SID\neq 0$입니다.
즉 우리는 SID가 0인지 아닌지를 통해 $x$와 $r$의 대소관계를 알 수 있습니다. 우리가 이러한 oracle을 갖고 있다는 것은 이분탐색을 통해 $r$의 값을 구할 수 있음을 의미합니다. $2\le p,q\le 2^{1024}$이며 각 로그인 시도에서 $r$의 MSB를 1비트씩 구할 수 있으므로 1024번의 로그인 시도로 $r$을 온전히 복구할 수 있습니다. 혹은, 512번의 로그인 시도로 상위 512비트를 구한 후 Coppersmith's method를 활용하여 512개의 LSB를 구할 수 있습니다. 1번 논문의 저자는 PoC에서 683번의 로그인 시도를 활용하여 RSA private key를 계산했습니다.
HNP-SUM: Cryptanalyzing MEGA in Six Queries and Other Applications (2번 논문)
2번 논문의 저자는 1번 논문에서 서술된 공격에 대해 다음과 같은 점을 지적했습니다.
- 1번 논문에서 이용하는 Coppersmith's method의 SOTA를 고려할 때, 로그인 시도의 수는 최소 512번 이상이다.
- 한 유저가 512번 로그인을 시도하는 것은 장기간의 수집이 필요하며, 현실적으로 불가능에 가깝다.
- 각 로그인 시도에서 유저는 344비트의 값을 반환하나, 이를 1비트의 정보로 치환하여 사용한다.
따라서 2번 논문의 핵심은 각 로그인 시도로부터 더 많은 정보를 얻는 것이며, 이는 CRT-RSA의 마지막 계산인
$$m \text{ := } ((m_p-m_q)u \text{ mod } p)q +m_q$$
가 Hidden Number Problem(이하 HNP)와 닮아있다는 것입니다. 저자는 이를 형식화하여 HNP-SUM을 소개합니다.
[HNP with Small Unknown Multiplier]
HNP-SUM에서 $N$, $a_i$, $T$, $E$가 주어지며 $1\le i \le n$인 $i$에 대해
$$\begin{align}a_i &\equiv_N t_ix+e_i\\\vert t_i\vert &\le T \\\vert e_i\vert &\le E\end{align}$$
를 만족하는 $x,t_i,e_i$가 존재합니다.
이때 공격자의 목표는 $t_i$를 부호, 공약수 정도의 오차로 구하는 것입니다.
[HNP-SUM to MEGA RSA Key Recovery]
HNP-SUM의 해결 방법을 다루기 전에, 이를 해결할 수 있을 때 MEGA에 어떻게 적용할 수 있는지 살펴보겠습니다.
모든 challenge $C$는 암호화된 shared key $ct$를 포함합니다. 이에 관해 몇가지 표기를 정의하겠습니다.
$$\begin{matrix}ct = ct_1\Vert ct_2\Vert\cdots\Vert ct_{41}\\ct_i = E_{\text{AES}}(pt_i)\\pt_i = D_{\text{AES}}(ct_i)\\pt = pt_1\Vert pt_2\Vert\cdots\Vert pt_{41}\end{matrix}$$
1번 논문에서와 유사하게 $u$의 값만이 변조된 상태를 생각해봅시다. 유저가 응답한 SID $s^\prime$는 다음과 같은 식을 만족합니다.
$$(m_p-m_q)u^\prime q +m_q\equiv_N e_1^\prime2^{b_1}+s^\prime2^{b_2}+2^{b_2-1}+e_2^\prime$$
$b_1,b_2$는 $s^\prime$을 제외한 $m$의 두 연속적인 부분의 위치를 나타내는 상수이며, $e_1^\prime,2^{b_2-1}+e_2^\prime$은 각 위치에 해당하는 $m$의 MSB, LSB입니다. $2^{b_2-1}$ 항은 $e_2^\prime$의 절댓값의 상한을 줄이기 위해 삽입되었습니다.
동일한 논리로, 같은 $m$과 다른 $u$값이 사용된 challenge의 유저 응답 $s^{\prime\prime}$에 대해서는 다음과 같은 식이 성립합니다.
$$(m_p-m_q)u^{\prime\prime} q +m_q\equiv_N e_1^{\prime\prime}2^{b_1}+s^{\prime\prime}2^{b_2}+2^{b_2-1}+e_2^{\prime\prime}$$
두 식을 빼면 다음과 같습니다.
$$(u^\prime-u^{\prime\prime})(m_p-m_q) q +m_q\equiv_N (e_1^\prime-e_1^{\prime\prime})2^{b_1}+(s^\prime-s^{\prime\prime})2^{b_2}+(e_2^\prime-e_2^{\prime\prime})$$
이때, 고정된 $i,j$에 대해 $ct^\prime,ct^{\prime\prime}$을 다음과 같이 구성합시다.
$$\begin{matrix}ct^\prime = ct_1\Vert ct_2\Vert \cdots \Vert ct_{33}\Vert ct_{i}\Vert ct_{i}\Vert \cdots\Vert ct_{i}\Vert ct_{41}\\ct^{\prime\prime} = ct_1\Vert ct_2\Vert \cdots \Vert ct_{33}\Vert ct_{i}\Vert ct_{i}\Vert \cdots\Vert ct_{j}\Vert ct_{41}\end{matrix}$$
이 경우 다음 식이 성립합니다. $\delta_{i,j}\text{ := }pt_i-pt_j$입니다.
$$u^\prime-u^{\prime\prime} = \delta_{i,j}2^{64}$$
위 식을 적용하여 서버가 획득한 정보를 다시 작성하면 다음과 같습니다.
$$2^{64}\delta_{i,j}(m_p-m_q) q +m_q\equiv_N (e_1^\prime-e_1^{\prime\prime})2^{b_1}+(s^\prime-s^{\prime\prime})2^{b_2}+(e_2^\prime-e_2^{\prime\prime})$$
이때 $x\text{ := }2^{64}(m_p-m_q)q, \Delta e_1\text{ := }e_1^\prime-e_1^{\prime\prime}, \Delta e_2\text{ := }e_2^\prime - e_1^{\prime\prime}, \Delta s\text{ := }s^\prime - s^{\prime\prime}$이라 하면 다음 식이 성립합니다.
$$\delta_{i,j}x\equiv_N \Delta e_1 2^{b_1} + \Delta s 2^{b_2} + \Delta e_2$$
위 식에서 $\Delta e_1$의 값만 알고 있다면, $t=\delta_{i,j},a = \Delta e_1 2^{b_1} + \Delta s 2^{b_2}$인 HNP-SUM의 instance로 볼 수 있습니다. 이때 $\vert \Delta e_1\vert< E_1\text{ := } 2^8$이므로 $\Delta e_1$은 brute-force를 통해 값을 알 수 있습니다.
즉, 서버는 각 로그인 시도로부터 $i,j$의 값을 바꿔가며 HNP-SUM의 식을 하나씩 획득할 수 있습니다. HNP-SUM에서 공격자의 목표가 $t_i$들을 복구하는 것이므로, 서버는 유용한 정보를 추출할 수 있도록 $\delta_{i,j}$를 선정해야 합니다. 2번 논문의 저자가 고른 방식은 다음과 같습니다.
- $i=18$로 고정합니다. 18번 블럭은 $d$가 포함된 두 번째 블럭이자 $d$의 비트만으로 구성된 첫 블럭입니다. 후술할 논리에 의해 이 값을 근사할 수 있습니다.
- $j$는 로그인 시도의 수에 따라 1부터 8까지를 사용합니다. 이는 $q$의 길이와 $q$의 상위 비트를 포함하는 블럭들입니다.
$2^{1024}$ 이상인 $m$을 랜덤하게 골라 고정하고 위와 같이 $ct$를 구성하여 로그인 시도를 수집하면 충분한 시도 수가 누적되었을 때 HNP-SUM을 통해 $\delta_{i,j}$를 구할 수 있습니다.
$\delta_{i,j}$를 올바르게 복구하였다고 가정합시다. RSA private exponent $d$는 다음 식을 만족합니다.
$$ed\equiv_{\phi(N)}1$$
이는 다음과 같은 정수 $k$가 존재함을 의미합니다.
$$ed=k\phi(N)+1=k(N-p-q+1)+1=kN-k(p+q-1)+1$$
또한, 비둘기집의 원리를 이용하여 그러한 음이 아닌 정수 $k$ 중 $e$ 이하인 것이 존재함을 알 수 있습니다.
이때, $p,q$가 $N$에 비해 매우 작으므로 $kN-k(p+q-1)+1$의 상위 약 1024비트는 $kN$과 동일함을 알 수 있습니다. 따라서 $pt_{18}$은 올바른 $k$에 대해 $\frac{kN}{e}$와 동일합니다.
서버는 $k$의 값을 알지 못하므로 0 이상 $e$ 미만의 모든 $k$에 대해 $pt_{18}$의 후보 $e$개를 획득합니다.
한편, $pt_1$의 첫 2바이트는 $l(q)$로 구성되어있습니다. $q$는 1024비트 정수이므로 이는 0x400의 값을 갖습니다. 따라서 이전에 구한 $e$개의 $pt_{18}$ 후보들이 구해진 $\delta_{18,1}$과 xor하여 상위 2바이트가 올바른 $l(q)$의 값인지 확인함으로써 서버는 각 $k$ 후보값을 검증할 수 있습니다.
올바르지 않은 $k$ 후보값에 대해 상위 2바이트는 uniform random의 결과값이라 간주하면, 올바르지 않은 $k$값이 검증을 통과할 false positive의 확률은 $\frac{e}{65536}$입니다. MEGA의 웹 클라이언트가 $e=257$을 활용하므로, 이 경우 거의 확실하게 유일한 $k$값의 후보를 얻게 됩니다.
올바른 $k$의 값을 획득하면 마찬가지로 $pt_j$의 값도 알 수 있습니다. 각 로그인 시도로부터 해당 값을 계산한 후 Coppersmith's method를 이용하면 6~7개 정도의 $\delta_{i,j}$ 값을 통해 public moduli $N$을 소인수분해할 수 있습니다.
[How to solve HNP-SUM with $n=2$]
$n=2$일 때, 공격자는 다음 관계를 만족하는 $N,a_1,a_2,T,E$를 알고 있다고 가정합니다.
$$\begin{matrix}a_1&\equiv_N& t_1x+e_1\\a_2&\equiv_N& t_2x+e_2\\\vert t_1\vert,\vert t_2\vert &\le& T\\\vert e_1\vert,\vert e_2\vert &\le& E\\\end{matrix}$$
이때 두 식의 적절한 선형조합으로 다음 식을 얻을 수 있습니다.
$$\begin{matrix}t_2a_1-t_1a_2&\equiv_N&t_2(t_1x+e_1)-t_1(t_2x+e_2)\\&\equiv_N&t_2e_1-t_1e_2\end{matrix}$$
위 값의 절댓값은 $2TE$ 이하로, $N$에 비해 작은 크기입니다. 따라서 다음의 격자 $B$는 짧은 벡터이며 SVP의 근사해로 추정되는 $(Et_2,-Et_1,t_1e_2-t_2e_1)$를 포함합니다.
$$B=\begin{bmatrix}E&0&a_1\\0&E&a_2\\0&0&N\end{bmatrix}$$
즉, $B$에 lattice reduction을 적용함으로써 공격자는 $t_1,t_2$를 얻을 수 있습니다. 다만 해당 값은 $g\text{ := }gcd(t_1,t_2)\neq1$인 경우 자명한 더 짧은 벡터 $(Et_2/g,-Et_1/g,(t_1e_2-t_2e_1)/g)$를 포함하므로 공격자는 부호와 공약수의 오차로 $t_1,t_2$를 계산할 수 있습니다.
[How to solve HNP-SUM with $n>2$]
$n=2$인 경우의 풀이로부터 자연스럽게 다음과 같은 격자 $B$를 생각해볼 수 있습니다.
$$B=\begin{bmatrix}E&&&&a_1\\&E&&&a_2\\&&\ddots&&\vdots\\&&&E&a_n\\&&&&N\end{bmatrix}$$
하지만 이 경우 lattice reduction으로 구한 SVP를 해석하는 것이 쉽지 않습니다. $n=2$인 경우와 다르게 $t_i$에 관한 식으로 SVP의 근사해를 표현하기 어렵기 때문입니다.
2번 논문의 저자는 두 행벡터만을 이용하여 구해진 부분격자(sublattice)들의 결과 역시 $N$에 비해서는 충분히 짧다는 사실을 이용하여 SVP의 근사해가 그러한 부분격자들의 선형 결합으로 표현될 확률이 높다고 가정합니다. 해당 가정이 참일 경우 각 부분격자에서의 가장 짧은 벡터들의 span은 $(n-1)$차원의 공간이 됩니다.
저자는 실험적으로 $B$에 대한 lattice reduction이 길이가 같은 선형 독립의 벡터 $(n-1)$개를 출력한다는 사실을 관찰하여 이를 뒷받침하였습니다.
이와 같은 결과를 활용하여 저자는 해당 $(n-1)$개의 벡터를 기저로 갖는 밀도 높은(dense) 부분격자 $B_\text{sub}$에 주목합니다.
$$\begin{matrix}b_i = i\text{-th row-vector of }B\\g_{i,j} = \gcd(t_i,t_j)\\v_{i,j} = t_jb_i/g_{i,j}+t_ib_j/g-k_{i,j}b_{n+1}\\B_\text{sub} = \{v_{i,j}\vert i,j\in\{1,\cdots,n\},i\neq j\}\end{matrix}$$
위와 같은 격자에 대해 저자는 다음의 $h_i$를 행벡터로 갖는 $B_\text{sub}$의 또다른 기저 $H$를 제시합니다. $H$는 upper-triangular matrix입니다.
$H$는 대각 위 성분들이 HNF의 조건 범위 내라는 보장이 없으므로 $B_\text{sub}$의 HNF와 완전히 일치하지는 않지만 leading non-zero term과 마지막 행을 변형하지 않는 행 연산을 통해 $B_\text{sub}$의 HNF를 만들 수 있습니다. 따라서 $H$를 구함으로써 $B_\text{sub}$의 HNF의 마지막 행을 계산할 수 있습니다.
이때, $u_{i,j}$는 $h_i$의 leading non-zero term을 최소화하는 계수로, 확장 유클리드 호제법을 통해 계산할 수 있습니다.
$$h_i = \begin{cases}\sum_{j=i+1}^{n} u_{i,j}v_{i,j} & \text{for } i<n-1\\v_{i,i+1}&\text{for }i=n-1\end{cases}$$
공격자는 $h_{n_1}$을 통해 $t_n$와 $t_{n-1}$의 값을 부호, 공약수의 오차로 구할 수 있음을 알 수 있습니다.
이러한 행렬의 정의는 각 $i$의 순서를 강제하지 않습니다. 따라서 적절히 순서를 바꿔가며 공격자는 전체 $t_i$를 계산할 수 있습니다.
여기까지의 내용으로 기본적인 공격의 골격을 알아보았습니다. 다만 위와 같은 과정만으로는 몇가지 한계가 존재합니다.
- 공격에서 사용 가능한 블럭의 수가 한정적이므로, 더 많은 로그인 시도를 확보할 수 있을 경우 사용할 페이로드의 수가 한정적입니다.
- 상위 8비트를 bruteforce하므로, 수행해야하는 lattice reduction의 수가 매우 많습니다.
따라서, 이후 내용에서는 위 3가지 한계에 대한 저자의 접근을 소개하겠습니다.
[How to make more available payloads]
해당 문제에 대한 해결법은 사실 간단합니다. 이전에 40번 블럭을 변조하여 $u$의 값을 바꾸었는데, 이를 대신하여 39, 38,...번 블럭을 변조하면 됩니다. 이와 같은 방법으로 다양한 $u$의 값으로부터 새로운 HNP-SUM 식을 얻을 수 있습니다.
이때 각 식에서 중복되는 $d_{i,j}$가 발생합니다. 이 경우 두 정보를 조합하여 더 압축적인 정보를 지닌 하나의 식으로 바꾸게 됩니다. 구체적으로는, 다음과 같은 식을 가진 상황입니다.
$$\begin{matrix}2^{128t}\delta_{i,j}x\equiv_N a_t-\epsilon_t\\2^{128t^\prime}\delta_{i,j}x\equiv_N a_{t^\prime}-\epsilon_{t^\prime}\end{matrix}$$
두 번째 식의 좌변은 첫 식의 좌변에 어떠한 상수를 곱한 값입니다. 따라서 두 식의 좌변을 각각 $y,ry$라 합시다.
첫 식으로부터 다음과 같은 사실을 알 수 있습니다.
$$y\in[a_t-E_1,a_1+E_1]$$
$$ry\in S_1=[ra_t-rE_1,ra_1+rE_1]$$
또한, 두 번째 식으로부터 다음과 같은 사실을 알 수 있습니다.
$$ry\in S_2\cup_{k=-\infty}^{\infty} [a_{t^\prime}-E_2+kN,a_{t^\prime}+E_2+kN]$$
이를 종합하면 $ry$는 $S_1\cap S_2$에 존재한다는 것을 알 수 있습니다. $S_1$,$S_2$의 각 구간의 길이는 $2rE_1+1$,$2E_2+1$이며 $S_2$의 각 구간 사이의 거리는 $N-2E_2-1$입니다. 이때 $S_1$의 길이가 $S_2$의 각 구간 사이의 거리보다 짧으므로 $S_1$은 $S_2$의 구간 중 최대 하나와 교차합니다. 해당 구간에 $ry$가 존재하므로 이와 같은 결과를 통해 $y$의 범위에 대한 두 식의 정보를 하나로 합칠 수 있습니다.
[How not to bruteforce MSBs]
상위 8비트를 bruteforce해야했던 가장 큰 이유 중 하나는, 모르는 비트의 위치가 불연속하면 lattice reduction을 통한 결과를 얻기 어렵기 때문입니다. 이와 같이 모르는 비트의 값이 2개의 연속한 위치로 표현되는 HNP의 변형 문제를 HNP-2H(2 Holes)라 하며 이 경우 다음과 같은 방법으로 해결할 수 있습니다.
핵심 아이디어는 $\Delta e_1C2^{b_1} \mod N$과 (\Delta e_2 C \mod N$을 동시에 작게 하는 $C$를 찾는 것입니다. 그러한 $C$를 잘 찾으면 공격자가 가진 HNP-SUM의 식들에서 $\Delta e_1$과 $\Delta e_2$의 영향을 연속한 LSB로 한정할 수 있습니다. 이는 다음과 같은 격자를 통해 구현됩니다.
$$B = \begin{bmatrix}E_1N&0\\E_12^{b_1}&E_2\end{bmatrix}$$
공격자는 lattice reduction을 통해 짧은 벡터 $v=E_1(C2^{b_1}\mod N),E_2C)$를 찾게 되며, Gaussian Heuristic에 의해 $C$는 다음과 같은 부등식을 만족합니다.
$$\begin{matrix}&\Vert v\Vert_2 \le \frac{2}{\sqrt{3}}\sqrt{\det B}=\frac{2}{\sqrt{3}}\sqrt{E_1E_2N}\\\Rightarrow&\vert \Delta e_1 C2^{b_1}+\Delta e_2C\mod N\vert\\\le&\vert\Delta e_1\vert\vert C2^{b_1}\mod N\vert+\vert\Delta e_2\vert\vert C\vert\\\le&E_1\vert C2^{b_1}\mod N\vert+E_2\vert C\vert\\\le&\Vert v\Vert_2+\Vert v\Vert_2\\\le&\frac{4}{\sqrt{3}}\sqrt{E_1E_2N}\end{matrix}$$
실제 공격에서 사용되는 값을 대입하여 위 식에서 보인 값의 상한을 확인하여 보면 약간의 정보손실이 존재하는 것을 확인할 수 있습니다. 다만 해당 기법을 통해 511번의 bruteforce를 피하고 HNP-SUM을 푸는 것만으로 문제를 해결할 수 있다는 장점이 있습니다.
Conclusion
본 글에서는 두 논문에서 MEGA의 구조적 취약점을 활용하여 유저의 RSA private key를 복구하는 과정을 살펴보았습니다.
특히 2번 논문에서는 격자를 활용한 정보 추출 방식과, 또다른 격자를 활용하여 공격을 최적화하는 방식을 확인하였습니다.
'ctf' 카테고리의 다른 글
2023 GoN Spring Qual writeup (0) | 2023.03.23 |
---|---|
쇼어 알고리즘 바닥부터 설명하기 (Shor's Algorithm explained from scratch) (1) | 2023.03.02 |
2022 Christmas CTF 후기 (0) | 2022.12.26 |
Whitehat Contest 2022 본선 Crypto writeup (0) | 2022.12.04 |
2022 Fall GoN Open Qual CTF Write-up (0) | 2022.08.28 |