迴圈移位異或加密
問題
在迴圈移位異或加密中,我們已知變換後的密文 y ,以及多個偏移的金鑰 ks ,要求出原文 x
方法
首先給出定理:在長度為 2 的方冪的二進位制串中,迴圈移位異或變換中,如果有奇數項,那麼這個變換是可逆的,否則就是不可逆的
例如說,我們討論有 3 項的情形
\[y = x \oplus (x \ggg p) \oplus (x \ggg q) \]對於此式,我們分別相應移位 p 和 q 位
\[y \ggg p = (x \ggg p) \oplus (x \ggg 2p) \oplus (x \ggg (p + q))\\ y \ggg q = (x \ggg q) \oplus (x \ggg 2q) \oplus (x \ggg (p + q)) \]此時我們可以利用 \(A \oplus A = 0\)
左式是可以求出的,記為 \(y^{(n)}\) ,而右式相當於將偏移位變為原來的兩倍,從而進行多次操作
\[y^{(n)} = x \oplus (x \ggg p \times 2^n) \oplus (x \ggg q \times 2^n) \]而對於長度為 2 的方冪的二進位制串,有
\[x = x \ggg p \times 2^n\\x = x \ggg q \times 2^n \]即
\[y^{(n)} = x \]類似的,我們可以證明項數為奇數的任意式成立
以下給出針對此方法的破解程式碼
def move(n, k): s = bin(n)[2:].zfill(64) k &= 63 return int(s[k:] + s[:k], 2) def encrypt(x, ks): return xor(x, reduce(xor, map(lambda k: move(x, k), ks))) def decrypt(y, ks): for _ in range(6): y = encrypt(y, ks) ks = [k << 1 for k in ks] return y
另一種方法
上面是一種直觀的方法,但是不夠嚴謹,下面介紹另一種方法:
對於 m 位二進位制數 \(a = {a_{m - 1}, a_{m - 2}, ..., a_{0}}\),對應多項式 \(a(x) = a_{m - 1}x^{m - 1} + a_{m - 2}x^{m - 2} + ... + a_{0}\)
我們定義方法 \(L(a) = (a \lll k_1) \oplus (a \lll k_2) \oplus ... \oplus (a \lll k_n)\)(右移位可以看作是左移位)
對 m 位二進位制數下迴圈左移 k 位等價於多項式乘以 \(x^k\) 後對多項式 \(x^m + 1\) 取模,即有
\[\begin{aligned} L(a) & = x^{k_1}a(x) + x^{k_2}a(x) + ... +x^{k_n}a(x) & \bmod(x^m + 1)\\ & = (x^{k_1} + x^{k_2} + ... + x^{k_n})a(x) & \bmod(x^m + 1)\\ & = k(x)a(x) & \bmod(x^m + 1) \end{aligned} \]對長度為 2 的方冪的二進位制數,有 \(x^{2^k} + 1\) 可以完全分解為 \((x + 1)^{2^k}\) ,從而只含有 \((x + 1)\) 這一個因子,從而判斷以 \(x^{2^k} + 1\) 為模的重模多項式環中元素存在逆元就變成了被判斷的多項式是否有 \(x +1\) 這個因子,只需判斷 \(k(1) = 0\) 與否
\[奇數項 \iff k(1) = 1 \iff 不含 x + 1 因子 \iff 有逆元\\ 偶數項 \iff k(1) = 0 \iff 含有 x + 1 因子 \iff 無逆元 \]證畢!