Block-Cipher

為什麼這些 Python XTEA 實現需要不同的增量?

  • January 30, 2021

我曾經需要一個從 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;
}

引用自:https://crypto.stackexchange.com/questions/12568