Python3中chr(183)与PHP中chr(183)进行base64编码后结果为何不同?

关于 python3 中 chr(183)和 php 中的 chr(183)分别进行 base64 编码后为什么结果不一样,我个人猜测可能是因为 python3 中的字符串不能直接进行 base64 编码,需要转换成 bytes 类型后才可以,可能是转换时候出现了问题,想问各位 v 友知道是什么情况吗

# -*- coding: utf-8 -*-
import base64
a = chr(183)
print(a)
print(base64.b64encode(bytes(a,encoding='utf-8')))
# 输出结果 b'wrc='
<?php
var_dump(base64_encode(chr(183)));
//输出结果 string(4) "tw=="

Python3中chr(183)与PHP中chr(183)进行base64编码后结果为何不同?

8 回复

因为你 py 的代码先 encode 了一次,导致 b7 前面加上了一字节的 utf8 前缀


这个问题涉及到Python和PHP在处理字符编码和Base64编码时的底层差异。核心原因在于chr()函数在两种语言中的行为不同,以及它们默认的字符串编码方式。

在Python 3中,字符串是Unicode对象。chr(183)返回的是Unicode码点U+00B7(中间点·)对应的字符。当这个字符串被编码为字节以进行Base64处理时,默认使用UTF-8编码。字符U+00B7在UTF-8中编码为两个字节:\xC2\xB7。对这两个字节进行Base64编码,结果自然是基于这两个字节的。

在PHP中,chr(183)函数直接返回一个值为183(0xB7)的单个字节。这个字节0xB7被直接送入Base64编码器。一个单独的字节0xB7的Base64编码结果,与两个字节序列\xC2\xB7的编码结果完全不同。

下面用代码直观展示这个区别:

Python 3 示例:

import base64

# Python3: chr(183) 返回Unicode字符 '·' (U+00B7)
char_py = chr(183)
print(f"字符: {char_py}, Unicode码点: {ord(char_py)}")

# 编码为字节(默认UTF-8)
bytes_py = char_py.encode('utf-8')
print(f"UTF-8字节: {bytes_py}") # 输出: b'\xc2\xb7'

# Base64编码
b64_py = base64.b64encode(bytes_py)
print(f"Base64结果: {b64_py}") # 输出: b'wrc='

PHP 等效对比:

<?php
// PHP: chr(183) 返回值为183 (0xB7) 的单个字节
$byte_php = chr(183);
echo "字节值: " . ord($byte_php) . "\n"; // 输出: 183

// 直接对这个字节进行Base64编码
$b64_php = base64_encode($byte_php);
echo "Base64结果: " . $b64_php . "\n"; // 输出: tw==
?>

关键总结:

  1. 源头不同:Python chr() 产出一个Unicode字符,PHP chr() 产出一个单字节。
  2. 中间转换:Python字符串在编码为字节时(如UTF-8)可能变为多个字节,而PHP的“字符串”在这里本身就是那个原始字节。
  3. 结果差异:对\xC2\xB7(两个字节)编码得到wrc=,对\xB7(一个字节)编码得到tw==

一句话建议: 确保在跨语言处理数据时,对字符串的编码和解码环节使用明确且一致的字符集(如UTF-8)。

那请问该如何避免这种情况

#2

base64.b64encode(bytes([183]))

问题是我这里 183 的结果是(ord(‘y’) + 10) ^ ord(‘4’)得出的,而且不止这一个,我要做的是把system这个字符串的每一位字母取出+10,也就是平移 10 个单位,然后system的每一位与 key = 'a4b0a0’的每一位异或后得到的值进行 base64 编码

base64.b64encode(bytes(a,encoding=‘latin-1’))

是由于两边编码不一致的原因引起的. 你在 php 那边. 先对 chr(183)进行 utf8_encode 一下的话. 在 base64 编码后的就是 b’wrc=’ (猜想的, 未验证)

确实是这样的,感谢老哥,我已经解决了

回到顶部