我遇到了一个我无法理解的怪异行为。
我正在使用mcrypt xtea(cfb模式)来加密某些数据。 由于php 7.2正在摆脱mcrypt,因为openssl也不支持Xtea,所以我必须自己实现算法。
问题是,无论使用何种算法:
我测试了这里提供的那个:pear implementation这只是一个ECB模式(没有初始向量)
维基百科页面上提供的那个stackoverflow topic
我在这里开发的(用于CFB模式)基于维基百科here和here以及可以找到的mcrypt源代码中的以下两篇文章{{3} }:
/*
* $v is the data, $k is the 128bits key and $iv is 64bits init vector (size = 8)
* Code is not optimized
*/
function encryptCfb($v, $k, $iv) {
$v = array_values(unpack('N*', $v));
$iv = array_values(unpack('N*', $iv));
$k = array_values(unpack('N*', $k));
$cipher = [];
//IV ciphering using the 128bits key
list ($v0, $v1) = cipher($iv[0], $iv[1], $k);
//Xoring the cipherd block with the first 64bits of data (32bits in V0 and 32 others in V1)
$cipher[0] = $v0 ^ $v[0];
$cipher[1] = $v1 ^ $v[1];
for ($i=2; $i < count($v); $i+=2) {
//Now ciphering the latest "cipherd" data using the 128bits key
list ($y, $z) = cipher($cipher[$i-2], $cipher[$i-1], $k);
//Xoring the cipherd block with the second 64bits of data (32bits in V0 and 32 others in V1)
$cipher[$i] = $y ^ $v[$i];
$cipher[$i+1] = $z ^ $v[$i+1];
}
$output = "";
foreach ($cipher as $i) {
$output .= pack('N', $i);
}
return $output;
}
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]);
$sum += $delta;
$v1 += ((($v0 << 4) ^ ($v0 >> 5)) + $v0) ^ ($sum + $k[($sum>>11) & 3]);
}
return [$v0, $v1];
}
我得到了不同的结果,而且没有一个给出mcrypt给出的完全相同的结果:
$cryptModule = mcrypt_module_open('xtea', '', 'ncfb', '');
mcrypt_generic_init($cryptModule, $key, $iv);
mcrypt_generic($cryptModule, $data);
您可以使用相同的数据/键/ IV检查和测试我在此处进行的不同测试:
here。请注意:
有谁知道为什么我得到不同的结果?
答案 0 :(得分:0)
有人知道我为什么会得到不同的结果吗?
我没有,但是我怀疑所有旧版本(2006年或更早的版本)的userland-php-implementations都没有经过测试,并且不能在64位PHP上运行。
我只需要在项目中使用XTEA,就像您一样,我测试了所有其他可用的XTEA实现,它们都是l = [(0,"a"), (1,"b"), (2,"c"), (3,"d"), (4,"e"), (5,"f"), (6,"g")]
df = spark.createDataFrame(l, schema=["_index", "item"])
# just get the value out of the row
start = df.filter(df.item == "c").select("_index").first()[0]
df.filter((df._index > start) & (df._index <= random.randint(start + 1, start + 4))).show()
,而且都没有产生正确的结果(我怀疑2006年-并且较旧的实现从未在64位系统上进行过测试,并且无法在64位系统上运行)
长话短说,我从头开始用PHP写了一个64位兼容的XTEA实现,代码可以在这里找到:https://github.com/divinity76/php-xtea
示例
very old
应输出如下内容:
<?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长度填充,长度有所不同,可以通过改写来禁用
string(13) "Hello, World!"
string(16) "□□Jx□□□□□□□ܴ9"
string(16) "Hello, World! "
这将为您提供:
XTEA::encrypt($data, $keys_array, XTEA::PAD_NONE);
因为XTEA算法要求要加密的数据为8字节的倍数。但是如果我们将其更改为
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);
答案 1 :(得分:-1)
它应该与$ v0和$ v1上的模数一起使用:
<Text style={{fontSize: 20, fontFamily: 'Century', fontWeight: '900', fontStyle: 'oblique'}}>ASD</Text>
您还需要调整输入值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];
}
的大小以确保其长度正确,例如使用您提到的PEAR模块$v
的{{1}}函数。