我正在尝试转换PHP
片段进入Python3
代码但输出 print
和echo
是不同的。
您可以在步骤 1 中看到它。
你知道问题出在哪里吗?我也附加了输入数组,但我认为它们是相等的。
�W2+ vs ee7523b2
编辑
当我将 raw 从 TRUE 切换为 FALSE 时,第一步的输出是相同的。 $d = strrev(hash("crc32b", $d, FALSE)) . $d
但问题是我必须将 PHP 转换为 Python,而不是相反,因为,然后我在步骤 2 中使用它,我需要具有相同的输出。
PHP 输出(CMD)
0 -> 1 1 100 EUR 20190101 11111111 Faktúra 1 SK6807200002891987426353 0 0
1 -> �W2+ 1 1 100 EUR 20190101 11111111 Faktúra 1 SK6807200002891987426353 0 0
2 -> 00004e00007715c242b04d5014490af1445dd61c1527ddc5f4461ca5886caf63fd8fbcf7df69c2035760ecb28d8171efdb409c0206996498ea7921e715172e60c210f923f070079ffba40000
Python 输出
-------
0 -> 1 1 100 EUR 20190101 11111111 Faktúra 1 SK6807200002891987426353 0 0
1 -> ee7523b2 1 1 100 EUR 20190101 11111111 Faktúra 1 SK6807200002891987426353 0 0
2 -> b'00006227515c7830302762275c783030325c7865305c7864386a34585c7862346d5c7838665c7865625c7863315c786266625c7839625c786339675c786332785c7831645c7862392c415c7862625c7831645c78663770365c786463735c786236572d606c225c7865355c7865635c7831345c7863655c786331205c7830635c7831315c7861375c7839345c7864665c7865635c7830365c7831652c22265c7866355c7862335c7866345c78616145585c7861625c7866395c7839615c7839645c7865645c7864625c7830305c7864355c7861643b5c7865365f5c7866645c786533405c78303027'
PHP
<?php
$suma = "100";
$datum = "20190101";
$varsym = "11111111";
$konsym = "";
$specsym = "";
$poznamka = "Faktúra";
$iban = "SK6807200002891987426353";
$swift = "";
$d = implode("\t", array(
0 => '',
1 => '1',
2 => implode("\t", array(
true,
$suma, // SUMA
'EUR', // JEDNOTKA
$datum, // DATUM
$varsym, // VARIABILNY SYMBOL
$konsym, // KONSTANTNY SYMBOL
$specsym, // SPECIFICKY SYMBOL
'',
$poznamka, // POZNAMKA
'1',
$iban, // IBAN
$swift, // SWIFT
'0',
'0'
))
));
// 0
echo "0 -> ".$d."\n";
$d = strrev(hash("crc32b", $d, TRUE)) . $d;
// 1
echo "1 -> ".$d."\n";
$x = proc_open("/usr/bin/xz '--format=raw' '--lzma1=lc=3,lp=0,pb=2,dict=128KiB' '-c' '-'", [0 => ["pipe", "r"], 1 => ["pipe", "w"]], $p);
fwrite($p[0], $d);
fclose($p[0]);
$o = stream_get_contents($p[1]);
fclose($p[1]);
proc_close($x);
$d = bin2hex("\x00\x00" . pack("v", strlen($d)) . $o);
// 2
echo "2 -> ".$d."\n";
?>
Python
def crc32b(x):
h = zlib.crc32(x)
x='%08X' % (h & 0xffffffff,)
return x.lower()
t = "\t"
gen = t.join(["1",
"100", # SAME VARIABLES
"EUR",
"20190101",
"11111111",
"",
"",
"",
"Faktúra",
"1",
"SK6807200002891987426353",
"",
"0",
"0"]
)
d = t.join([
"", "1", gen])
# 0
print(f"0 -> {d}")
hashD = crc32b(d.encode()) # OK
hashD = hashD[::-1]
# hashD = str(binascii.unhexlify(hashD))
d = hashD + d
# 1
print(f"1 -> {d}")
args = shlex.split("xz '--format=raw' '--lzma1=lc=3,lp=0,pb=2,dict=128KiB' -c -")
process = subprocess.Popen(args, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output = process.communicate(d.encode())
pack = "\x00\x00" + str(struct.pack("H", len(d))) + str(output[0])
d = binascii.hexlify(pack.encode())
# 2
print(f"2 -> {d}")
最佳答案
无法使用PHP。
根据[Python.Docs]: zlib.crc32(data[, value]) (强调是我的):
Computes a CRC (Cyclic Redundancy Check) checksum of data. The result is an unsigned 32-bit integer.
您混淆了:
它的值 - 也可以被视为长度为 4的 ASCII 字符串
其值的文本表示(以基16为单位) - 这是一个长度为8的字符串
>>> crc = 0x2B3257EE # The value returned by zlib.crc32 for your text >>> type(crc), crc (<class 'int'>, 724719598) >>> >>> [chr((crc >> shift_bits) & 0xFF) for shift_bits in [0, 8, 16, 24]] ['î', 'W', '2', '+']
注释:
一种方法是将数字的 4 个字节转换为 char
要从 uint32 值中获取一个字节,uint32 必须按该 的顺序向右移动 ( [Python.Wiki]: BitwiseOperators )值中的字节 ([3, 2, 1, 0]) 乘以8 (一个字节中的位数)
- 此外,为了消除不需要的字节(除了最右边的字节之外的任何字节),结果值也会用 0xFF 进行和编辑(>255)
由于小端特性,字节会以相反的顺序(从右到左)转换为char
第一个stchar('î')看起来不同,但它只是一个代表问题(在我的控制台与你的控制台中)
将其集成到您的代码中,您需要修改您的crc32b函数(并删除对hashD的任何进一步处理)以:
def crc32b(x):
crc = zlib.crc32(x)
return "".join([chr((crc >> shift_bits) & 0xFF) for shift_bits in [0, 8, 16, 24]])
有关此一般主题的更多详细信息,请查看 [SO]: Python struct.pack() behavior (@CristiFati's answer) .
<小时/>
更新#0
添加从十六进制表示形式开始的版本:
>>> crc = 0x2B3257EE >>> crc_hex = "{:08X}".format(crc) >>> crc_hex '2B3257EE' >>> >>> list(reversed([chr(int(crc_hex[2 * i] + crc_hex[2 * i + 1], 16)) for i in range(len(crc_hex) // 2)])) ['î', 'W', '2', '+']
从我的PoV来看,这更丑陋,而且效率低下(许多来回转换),但无论如何都要发布,因为有些人在位操作上遇到困难
关键点是一次处理2个hex char,并且转换后只进行反转
关于php - PHP 中 crc32b 的输出不等于 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54712872/