Block-Cipher
為什麼這些 Python XTEA 實現需要不同的增量?
我曾經需要一個從 C++ 到 Python 的 XTEA 片段,但它不能正常工作。然後我在 ActiveState.com 上找到了一個函式,並註意到它看起來幾乎和我的一模一樣,除了一個例外——由於某種原因,它的“delta”變數被改變了。這是測試程式碼:
import struct def XTEA_encrypt(buf, k): ret = bytearray() for offset in range(int(len(buf)/8)): v0 = struct.unpack("<I", bytes(buf[offset*8:offset*8+4]))[0] v1 = struct.unpack("<I", bytes(buf[offset*8+4:offset*8+8]))[0] delta = 0x9E3779B9 sum_ = 0 for _ in range(32): v0 = (v0 + ((v1<<4 ^ v1>>5) + v1) ^ (sum_ + k[sum_ & 3])) & 0xFFFFFFFF sum_ = (sum_ + delta) & 0xFFFFFFFF v1 = (v1 + ((v0<<4 ^ v0>>5) + v0) ^ (sum_ + k[sum_>>11 & 3])) & 0xFFFFFFFF ret += struct.pack("<I", v0) + struct.pack("<I", v1) return ret print(repr(XTEA_encrypt('\xfc\xd9\xd8A\x0b\xc4~\x82', [4060739823, 3225438839, 2808461571, 1241583342])))
使用 new ,程式碼按預期
delta = 0x9E3779B9
列印。\xec\xe8\xeaZ!\xec7\xde
另一方面,原始的 C++ 實現(https://github.com/otland/forgottenserver/blob/788198e1afd96a0b83ddeb025a9f3910e72626d5/src/protocol.cpp#L87)有delta = 0x61C88647
,導致\x87Z\xed})\t:\xbe
被列印。為什麼實現不同?
如果您仔細查看 C++ 實現的第 105 行,您會發現它從總和中減去**delta而不是相加:
103 for (int32_t i = 32; --i >= 0;) { 104 v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]); 105 sum -= delta; 106 v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum >> 11 & 3]); 107 }
自從 $ \textrm{0x61C88647+0x9E3779B9}=2^{32} $ ,這相當於添加“正常”增量。
如果你問我,這是一個相當奇怪的設計選擇,但它確實有效。
0x61C88647
是 的 2 的補碼表示-0x9E3779B9
。您可以將 XTEA 實現為:void XTEA_Encrypt(uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9; for (i=0; i < 32; i++) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); sum += delta; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); } v[0]=v0; v[1]=v1; }
或者
void XTEA_Encrypt(uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0=v[0], v1=v[1], sum=0, delta=0x61C88647; for (i=0; i < 32; i++) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); sum -= delta; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); } v[0]=v0; v[1]=v1; }