php xtea实现(cfb)

php xtea实现(cfb),php,encryption,mcrypt,xtea,Php,Encryption,Mcrypt,Xtea,我遇到了一种我无法理解的奇怪行为 我正在使用mcryptxtea(cfb模式)加密一些数据。 由于PHP7.2摆脱了mcrypt,而且openssl也不支持Xtea,所以我不得不自己实现该算法 问题是,无论采用何种算法: 我测试了这里提供的一个:它只是ECB模式(没有初始向量) wikipedia页面上提供的是从这个 我在这里开发的一个(针对CFB模式)基于以下两篇文章,分别来自wikipedia和mcrypt源代码,可以找到: 您可以使用相同的数据/密钥/IV检查和测试我在此处进行的不同测试

我遇到了一种我无法理解的奇怪行为

我正在使用mcryptxtea(cfb模式)加密一些数据。 由于PHP7.2摆脱了mcrypt,而且openssl也不支持Xtea,所以我不得不自己实现该算法

问题是,无论采用何种算法:

  • 我测试了这里提供的一个:它只是ECB模式(没有初始向量)

  • wikipedia页面上提供的是从这个

  • 我在这里开发的一个(针对CFB模式)基于以下两篇文章,分别来自wikipedia和mcrypt源代码,可以找到:

    您可以使用相同的数据/密钥/IV检查和测试我在此处进行的不同测试:

    • 。请注意:

      • 轮数不变(32或64)
      • 使用N模式(大端)或V模式(小端)打包/解包不会改变任何内容
    • !

    • !


    有人知道我为什么会得到不同的结果吗?

    它应该与$v0和$v1上的模数一起工作:

    function cipher($v0, $v1, $k) {
        $delta = 0x9e3779b9;
        $sum = 0;
        $limit = $delta * 32;
    
        for ($i=0; $i < 32; $i++) {
            $v0 += ((($v1<<4) ^ ($v1>>5)) + $v1) ^ ($sum + $k[$sum & 3]);
            $v0 = $v0 % pow(2, 32);
            $sum += $delta;
            $v1 += ((($v0 << 4) ^ ($v0 >> 5)) + $v0) ^ ($sum + $k[($sum>>11) & 3]);
            $v1 = $v1 % pow(2, 32);
        }
    
        return [$v0, $v1];
    }
    
    函数密码($v0,$v1,$k){
    $delta=0x9e3779b9;
    $sum=0;
    $limit=$delta*32;
    对于($i=0;$i<32;$i++){
    $v0+=(($v15))+$v1^($sum+$k[$sum&3]);
    $v0=$v0%功率(2,32);
    $sum+=$delta;
    $v1+=(($v0>5))+$v0^($sum+$k[($sum>>11)和3]);
    $v1=$v1%pow(2,32);
    }
    返回[$v0,$v1];
    }
    
    您还需要调整输入值
    $v
    的大小,以确保其长度正确,例如使用您提到的PEAR模块
    Crypt\u Xtea
    \u resize(&$data,$size,$nonull=false)
    函数

    有人知道为什么我会得到不同的结果吗

    我不知道,但我怀疑所有旧的(2006年和更老的?)userland php实现从未在上面测试过,也不适用于64位php

    我只是在一个项目中使用了XTEA,像你一样,我测试了所有其他可用的XTEA实现,它们都是非常古老的,没有一个产生了正确的结果(我怀疑所有2006年和更早的实现从未在64位系统上测试过,并且它们在64位系统上不工作)

    长话短说,我从头开始用PHP编写了一个64位兼容的XTEA实现,代码可以在这里找到:

    例子

    <?php 
    require_once('XTEA.class.php');
    $key_binary = "secret";
    $keys_array = XTEA::binary_key_to_int_array($key_binary);
    $data = "Hello, World!";
    $encrypted = XTEA::encrypt($data, $keys_array);
    $decrypted = XTEA::decrypt($encrypted, $keys_array);
    var_dump($data, $encrypted, $decrypted);
    
    由于存在长度填充,因此长度不同,可以通过执行以下操作来禁用

    XTEA::encrypt($data, $keys_array, XTEA::PAD_NONE);
    
    这将给你:

    PHP Fatal error:  Uncaught InvalidArgumentException: with PAD_NONE the data MUST be a multiple of 8 bytes! in /cygdrive/c/projects/tibia_login_php/xtea.class.php:73
    Stack trace:
    #0 /cygdrive/c/projects/tibia_login_php/xtea_tests.php(8): XTEA::encrypt('Hello, World!', Array, 0)
    #1 {main}
      thrown in /cygdrive/c/projects/tibia_login_php/xtea.class.php on line 73
    
    因为XTEA算法要求要加密的数据是8字节的倍数。但是如果我们把它改成

    <?php 
    require_once('XTEA.class.php');
    $keys_binary = "secret";
    $keys_array = XTEA::binary_key_to_int_array($keys_binary);
    $data = "Hello, World!123";
    $encrypted = XTEA::encrypt($data, $keys_array, XTEA::PAD_NONE);
    $decrypted = XTEA::decrypt($encrypted, $keys_array);
    var_dump($data, $encrypted, $decrypted);
    
    • 没有填充,没有长度变化,没有例外
    ($sum+$k[$sum&3])
    可能会溢出无符号32位int(至少在64位PHP上)并损坏输出<代码>$sum+=$delta可能会溢出无符号32位int(至少在64位PHP上)并损坏输出<代码>($sum+$k[($sum>>11)&3]可能会溢出无符号32位int(至少在64位PHP上)并损坏输出。可能(我对此表示怀疑,但可能)此代码在32位PHP上有效,但在64位PHP上无效。
    XTEA::encrypt($data, $keys_array, XTEA::PAD_NONE);
    
    PHP Fatal error:  Uncaught InvalidArgumentException: with PAD_NONE the data MUST be a multiple of 8 bytes! in /cygdrive/c/projects/tibia_login_php/xtea.class.php:73
    Stack trace:
    #0 /cygdrive/c/projects/tibia_login_php/xtea_tests.php(8): XTEA::encrypt('Hello, World!', Array, 0)
    #1 {main}
      thrown in /cygdrive/c/projects/tibia_login_php/xtea.class.php on line 73
    
    <?php 
    require_once('XTEA.class.php');
    $keys_binary = "secret";
    $keys_array = XTEA::binary_key_to_int_array($keys_binary);
    $data = "Hello, World!123";
    $encrypted = XTEA::encrypt($data, $keys_array, XTEA::PAD_NONE);
    $decrypted = XTEA::decrypt($encrypted, $keys_array);
    var_dump($data, $encrypted, $decrypted);
    
    string(16) "Hello, World!123"
    string(16) "%t□□□n□□aʓ'□□H"
    string(16) "Hello, World!123"