-
Notifications
You must be signed in to change notification settings - Fork 169
refactor(encoder): remove Base58 and rename Base64 methods #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
审阅者指南重构加密编码工具,移除自定义的 Base58 实现,统一 Base64 编码器方法命名,并引入专用的 X3 Base64 编解码支持,同时更新 client、config 和测试以使用新的基于 Base64 的行为和前缀。 使用 Base64 进行 x3 签名编码/解码的时序图sequenceDiagram
title "Sequence diagram for x3 signature encode/decode using Base64"
actor "Caller" as Caller
participant "Client" as Client
participant "CryptoProcessor" as CryptoProcessor
participant "BitOperations" as BitOperations
participant "Base64Encoder" as Base64Encoder
rect rgb(230,230,250)
Note over Caller,Base64Encoder: "Encode x3 signature (signing flow)"
"Caller" ->> "Client": "_build_signature(d_value, a1_value, xsec_appid, string_param)"
"Client" ->> "CryptoProcessor": "build_payload_array(d_value, a1_value, xsec_appid, string_param)"
"CryptoProcessor" -->> "Client": "payload_array: list[int]"
"Client" ->> "BitOperations": "xor_transform_array(payload_array)"
"BitOperations" -->> "Client": "xor_result: list[int]"
"Client" ->> "Base64Encoder": "encode_x3(xor_result as bytes)"
"Base64Encoder" -->> "Client": "x3_signature_base64: str"
"Client" -->> "Caller": "x3_signature_base64: str"
end
rect rgb(220,245,220)
Note over Caller,Base64Encoder: "Decode x3 signature (verification flow)"
"Caller" ->> "Client": "decode_x3(x3_signature: str)"
"Client" ->> "Client": "strip_prefix(X3_PREFIX)"
"Client" ->> "Base64Encoder": "decode_x3(x3_signature_without_prefix)"
"Base64Encoder" -->> "Client": "decoded_bytes: bytes"
"Client" ->> "BitOperations": "xor_transform_array(list(decoded_bytes))"
"BitOperations" -->> "Client": "original_payload_array: list[int]"
"Client" -->> "Caller": "original_payload_array as bytearray"
end
文件级变更
针对关联 Issue 的评估
可能相关的 Issue
提示与命令与 Sourcery 交互
自定义你的体验打开你的 控制面板 以:
获取帮助Original review guide in EnglishReviewer's GuideRefactors the crypto encoding utilities to remove the custom Base58 implementation, standardize Base64 encoder method names, and introduce dedicated X3 Base64 encode/decode support, updating the client, config, and tests to use the new Base64-based behavior and prefixes. Sequence diagram for x3 signature encode/decode using Base64sequenceDiagram
title "Sequence diagram for x3 signature encode/decode using Base64"
actor "Caller" as Caller
participant "Client" as Client
participant "CryptoProcessor" as CryptoProcessor
participant "BitOperations" as BitOperations
participant "Base64Encoder" as Base64Encoder
rect rgb(230,230,250)
Note over Caller,Base64Encoder: "Encode x3 signature (signing flow)"
"Caller" ->> "Client": "_build_signature(d_value, a1_value, xsec_appid, string_param)"
"Client" ->> "CryptoProcessor": "build_payload_array(d_value, a1_value, xsec_appid, string_param)"
"CryptoProcessor" -->> "Client": "payload_array: list[int]"
"Client" ->> "BitOperations": "xor_transform_array(payload_array)"
"BitOperations" -->> "Client": "xor_result: list[int]"
"Client" ->> "Base64Encoder": "encode_x3(xor_result as bytes)"
"Base64Encoder" -->> "Client": "x3_signature_base64: str"
"Client" -->> "Caller": "x3_signature_base64: str"
end
rect rgb(220,245,220)
Note over Caller,Base64Encoder: "Decode x3 signature (verification flow)"
"Caller" ->> "Client": "decode_x3(x3_signature: str)"
"Client" ->> "Client": "strip_prefix(X3_PREFIX)"
"Client" ->> "Base64Encoder": "decode_x3(x3_signature_without_prefix)"
"Base64Encoder" -->> "Client": "decoded_bytes: bytes"
"Client" ->> "BitOperations": "xor_transform_array(list(decoded_bytes))"
"BitOperations" -->> "Client": "original_payload_array: list[int]"
"Client" -->> "Caller": "original_payload_array as bytearray"
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - 我已经审查了你的改动,这里是一些反馈:
- 由于 encode_to_b64/decode_from_b64 已经重命名为 encode/decode,建议保留一些轻量级、向后兼容的别名(或一个弃用层),以避免破坏现有使用该 encoder API 的下游代码。
- CUSTOM_BASE64_ALPHABET 和 X3_BASE64_ALPHABET 当前值完全相同;建议复用同一个常量,或者在语义上更清晰地区分它们,以避免未来不小心偏离或造成困惑。
给 AI Agent 的提示词
Please address the comments from this code review:
## Overall Comments
- 由于 encode_to_b64/decode_from_b64 已经重命名为 encode/decode,建议保留一些轻量级、向后兼容的别名(或一个弃用层),以避免破坏现有使用该 encoder API 的下游代码。
- CUSTOM_BASE64_ALPHABET 和 X3_BASE64_ALPHABET 当前值完全相同;建议复用同一个常量,或者在语义上更清晰地区分它们,以避免未来不小心偏离或造成困惑。
## Individual Comments
### Comment 1
<location> `src/xhshow/utils/encoder.py:96-101` </location>
<code_context>
+ raise ValueError("Invalid Base64 input: unable to decode string") from e
+ return decoded_bytes
+
+ def encode_x3(self, input_bytes: bytes | bytearray) -> str:
+ """
+ Encode x3 signature using X3_BASE64_ALPHABET
+
+ Args:
+ input_bytes: Input byte data
+
+ Returns:
+ str: Base64 encoded string with X3 custom alphabet
+
+ Raises:
+ ValueError: Base64 encoding failed
+ """
+ try:
+ standard_encoded_bytes = base64.b64encode(input_bytes)
+ standard_encoded_string = standard_encoded_bytes.decode("utf-8")
+ except (binascii.Error, ValueError) as e:
+ raise ValueError("Failed to encode to Base64") from e
+
</code_context>
<issue_to_address>
**suggestion:** 围绕 base64.b64encode 的 try/except 很可能是不必要的,并且可能会掩盖一些意料之外的错误。
根据当前的类型标注(bytes | bytearray),base64.b64encode 在现实场景下不太可能抛出 binascii.Error 或 ValueError。这样宽泛地捕获这些异常并重新抛出一个通用的 ValueError,会在传入异常类型时掩盖编程错误。建议移除这段 try/except,或者只在 decode_x3 这条会处理外部无效输入的路径上做错误处理。
```suggestion
standard_encoded_bytes = base64.b64encode(input_bytes)
standard_encoded_string = standard_encoded_bytes.decode("utf-8")
```
</issue_to_address>
### Comment 2
<location> `src/xhshow/config/config.py:18-23` </location>
<code_context>
STANDARD_BASE64_ALPHABET = (
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
)
CUSTOM_BASE64_ALPHABET = (
"ZmserbBoHQtNP+wOcza/LpngG8yJq42KWYj0DSfdikx3VT16IlUAFM97hECvuRX5"
)
- BASE58_BASE = 58 # Base58 radix
- BYTE_SIZE = 256 # Byte size (2^8)
+ X3_BASE64_ALPHABET = (
+ "ZmserbBoHQtNP+wOcza/LpngG8yJq42KWYj0DSfdikx3VT16IlUAFM97hECvuRX5"
+ )
</code_context>
<issue_to_address>
**suggestion:** CUSTOM_BASE64_ALPHABET 和 X3_BASE64_ALPHABET 目前重复了同一个字面量字符串,这存在后续偏离(drift)的风险。
既然它们当前使用完全相同的字符串,建议通过引用来定义其中一个常量(例如 X3_BASE64_ALPHABET = CUSTOM_BASE64_ALPHABET),以避免未来维护时出现差异。如果它们在概念上本来就应该不同,那么现在就给 X3_BASE64_ALPHABET 一个不同的值会更清晰。
```suggestion
CUSTOM_BASE64_ALPHABET = (
"ZmserbBoHQtNP+wOcza/LpngG8yJq42KWYj0DSfdikx3VT16IlUAFM97hECvuRX5"
)
# X3_BASE64_ALPHABET 当前使用与 CUSTOM_BASE64_ALPHABET 相同的字符表。
# 通过引用 CUSTOM_BASE64_ALPHABET 来定义,可以避免重复和未来的偏离风险。
X3_BASE64_ALPHABET = CUSTOM_BASE64_ALPHABET
```
</issue_to_address>
### Comment 3
<location> `tests/test_crypto.py:49-52` </location>
<code_context>
- # 验证Base58字符
- for char in result:
- assert char in self.crypto.config.BASE58_ALPHABET
+ # Base58已移除,此测试不再需要
+ pass
def test_base64_encoder(self):
</code_context>
<issue_to_address>
**suggestion (testing):** 与其保留一个对已移除 Base58 功能的空操作测试,不如重构或直接删除这个测试。
现在把这里改成了 `pass`,会产生误导,而且在 Base58 已经移除的情况下也没有任何价值。请考虑:要么删除这条测试,要么将其重用在新的 Base64 x3 行为上(例如通过 `Base64Encoder.encode_x3`/`decode_x3` 做往返编解码测试,和/或断言 x3 编码输出仅使用 `config.X3_BASE64_ALPHABET` 中的字符)。这样可以为替代 Base58 的新编码路径保持足够的测试覆盖。
```suggestion
def test_base64_x3_encoder(self):
"""测试自定义Base64 x3 编码"""
test_string = "Hello, World!"
# 编码
encoded = self.crypto.b64encoder.encode_x3(test_string)
# 基本属性检查
assert isinstance(encoded, str)
assert len(encoded) > 0
# 校验只包含自定义X3 Base64字符表中的字符
for char in encoded:
assert char in self.crypto.config.X3_BASE64_ALPHABET
# 解码并验证与原始字符串一致
decoded = self.crypto.b64encoder.decode_x3(encoded)
assert decoded == test_string
```
</issue_to_address>
### Comment 4
<location> `tests/test_crypto.py:57` </location>
<code_context>
"""测试自定义Base64编码"""
test_string = "Hello, World!"
- result = self.crypto.b64encoder.encode_to_b64(test_string)
+ result = self.crypto.b64encoder.encode(test_string)
assert isinstance(result, str)
</code_context>
<issue_to_address>
**suggestion (testing):** 请扩展 Base64 测试,以覆盖重命名方法的编解码往返以及对非法输入的处理。
测试已经改为调用 `encode`,但目前只断言了调用成功和字符表。建议同时:
- 增加一个使用 `self.crypto.b64encoder.decode(result)` 的往返检查,并断言结果等于原始 `test_string`。
- 增加一个测试,验证当 `decode` 处理明显非法的 Base64 输入时会抛出 `ValueError`(例如填充错误或包含非法字符的字符串)。
这会更好地覆盖重命名后的 API 及其错误处理路径。
Suggested implementation:
```python
def test_base64_encoder(self):
"""测试自定义Base64编码"""
test_string = "Hello, World!"
# 调用重命名后的 encode 方法
result = self.crypto.b64encoder.encode(test_string)
# 结果应为字符串
assert isinstance(result, str)
# 编解码回原始字符串
decoded = self.crypto.b64encoder.decode(result)
assert decoded == test_string
def test_base64_decoder_invalid_input(self):
"""测试Base64解码对非法输入的异常处理"""
# 明显非法的Base64字符串(包含非法字符和错误的填充)
invalid_inputs = [
"!!!not_base64!!!",
"abcd=", # 错误填充
"ab=c", # 非法字符
"YWJj*", # 非法字符
]
for invalid in invalid_inputs:
with pytest.raises(ValueError):
self.crypto.b64encoder.decode(invalid)
```
1. 确保本测试文件顶部已经导入 `pytest`,例如:`import pytest`。如果尚未导入,需要在文件头部添加对应的 `import`。
2. 此修改假设 `self.crypto.b64encoder.decode` 对非法 Base64 输入会抛出 `ValueError`。如果实际实现抛出的是其他异常类型,需要将 `pytest.raises(ValueError)` 中的异常类型调整为实际的异常类型。
</issue_to_address>
### Comment 5
<location> `tests/test_crypto.py:56-65` </location>
<code_context>
-
- assert isinstance(result, str)
- assert len(result) > 0
- # 验证Base58字符
- for char in result:
- assert char in self.crypto.config.BASE58_ALPHABET
</code_context>
<issue_to_address>
**suggestion (testing):** 请更新签名相关测试,使其验证新的 Base64 x3 编码和解码行为。
我们已经移除了 `test_build_signature` 中与 Base58 相关的断言,但目前还没有针对新的 Base64/x3 行为做任何断言。为了在重构后保持等效的测试覆盖,建议:
- 在 `test_build_signature` 中,断言返回的签名:
- 在适用时具有期望的前缀(例如如果高层方法会添加 `config.X3_PREFIX`)。
- 只包含 `self.client.crypto_processor.config.X3_BASE64_ALPHABET` 中的字符。
- 为 `decode_x3` 添加更精确的测试,用以覆盖以下情况:
- 一个带前缀的 x3 签名,经过 `_build_signature` + `decode_x3`(包含 XOR 过程)往返后,可以恢复原始 payload 字节。
- 一个不带前缀的 x3 签名,以验证“前缀可选”的约定是否被遵守。
- 一个无效的 x3 字符串(使用错误的字母表或非法 Base64),是否会从 `Base64Encoder.decode_x3` 抛出预期的 `ValueError`。
这样可以确保 Base58 → Base64 x3 的迁移在测试层面被充分覆盖,并且 `decode_x3` 的契约得到强制约束。
Suggested implementation:
```python
def test_base58_encoder(self):
"""测试Base58编码"""
# Base58已移除,此测试不再需要
pass
def test_base64_encoder(self):
"""测试自定义Base64编码 (x3 Base64)"""
test_string = "Hello, World!"
result = self.crypto.b64encoder.encode(test_string)
# 返回值类型应该为字符串
assert isinstance(result, str)
# 签名不能为空
assert len(result) > 0
# 验证x3前缀及Base64字符
config = self.crypto.config
# 如果启用了前缀,则结果应以X3_PREFIX开头
if getattr(config, "X3_PREFIX", None):
if result.startswith(config.X3_PREFIX):
core = result[len(config.X3_PREFIX) :]
else:
# 如果结果未带前缀,则整个结果视为核心编码
core = result
else:
core = result
# 所有字符必须在x3 Base64字母表中
alphabet = config.X3_BASE64_ALPHABET
for ch in core:
assert ch in alphabet
def test_decode_x3_round_trip_with_prefix(self):
"""测试带前缀的x3签名: _build_signature + decode_x3 之后恢复原始payload"""
# 原始payload使用字节串, 与签名逻辑保持一致
payload = b"test payload for x3 with prefix"
xor_key = 0x42 # 任意非零的XOR key, 与生产/实现保持一致
# 通过签名构建方法生成带前缀的x3签名
# 这里假设crypto上有生成签名的方法, 名称按当前实现调整
signature = self.crypto._build_signature(payload, xor_key=xor_key, with_prefix=True)
config = self.crypto.config
# 确认签名具有预期前缀
assert signature.startswith(config.X3_PREFIX)
# 通过decode_x3解码 (内部会处理前缀 + XOR)
decoded = self.crypto.b64encoder.decode_x3(signature, xor_key=xor_key)
# 解码后应恢复为原始payload
assert isinstance(decoded, (bytes, bytearray))
assert decoded == payload
def test_decode_x3_round_trip_without_prefix(self):
"""测试不带前缀的x3签名: 前缀可选, 仍然可以正确解码"""
payload = b"test payload for x3 without prefix"
xor_key = 0x24
# 生成不带前缀的x3签名
raw_x3 = self.crypto.b64encoder.encode_x3(payload, xor_key=xor_key, with_prefix=False)
config = self.crypto.config
# 确认没有X3前缀
assert not raw_x3.startswith(config.X3_PREFIX)
# decode_x3 应该支持无前缀输入
decoded = self.crypto.b64encoder.decode_x3(raw_x3, xor_key=xor_key)
assert isinstance(decoded, (bytes, bytearray))
assert decoded == payload
def test_decode_x3_invalid_string_raises_value_error(self):
"""测试无效x3字符串时, Base64Encoder.decode_x3 抛出 ValueError"""
config = self.crypto.config
# 构造包含非法字符的x3字符串:
# - 使用合法前缀
# - 在核心部分注入不在X3_BASE64_ALPHABET中的字符
bad_char = "!" # 一般不会在Base64字母表中
assert bad_char not in config.X3_BASE64_ALPHABET
invalid_core = "AAAA" + bad_char + "BBBB"
invalid_x3 = f"{config.X3_PREFIX}{invalid_core}"
xor_key = 0x01
# decode_x3 遇到非法字符应抛出 ValueError
with pytest.raises(ValueError):
self.crypto.b64encoder.decode_x3(invalid_x3, xor_key=xor_key)
```
1. 上面的实现假设:
- `self.crypto` 暴露:
- `config.X3_PREFIX`
- `config.X3_BASE64_ALPHABET`
- 方法 `_build_signature(payload: bytes, xor_key: int, with_prefix: bool = True) -> str`
- `b64encoder.encode_x3(payload: bytes, xor_key: int, with_prefix: bool = True) -> str`
- `b64encoder.decode_x3(x3: str, xor_key: int) -> bytes`
如果你们当前API命名不同,请将 `_build_signature` / `encode_x3` / `decode_x3` 和参数名调整为实际实现。
2. 文件中还需要更新 `test_build_signature`:
- 使用 `signature = self.crypto._build_signature(...)` 或对应的签名方法。
- 若签名应始终带前缀, 断言 `signature.startswith(self.crypto.config.X3_PREFIX)`。
- 针对签名主体(去掉前缀后)逐字符断言 `in self.crypto.config.X3_BASE64_ALPHABET`,替换掉原来的 Base58 字母表断言。
3. 如果你们的测试用例类当前没有 `pytest` 导入, 需要在 `tests/test_crypto.py` 顶部添加 `import pytest`。
4. 若XOR key的来源固定在配置/常量(而不是测试中硬编码), 请将测试中的 `xor_key` 调整为与生产逻辑一致的值或从配置中读取。
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈持续改进 Review 质量。
Original comment in English
Hey there - I've reviewed your changes - here's some feedback:
- Since encode_to_b64/decode_from_b64 were renamed to encode/decode, consider keeping lightweight backward-compatible aliases (or a deprecation layer) to avoid breaking existing consumers of the encoder API.
- CUSTOM_BASE64_ALPHABET and X3_BASE64_ALPHABET currently have identical values; consider reusing a single constant or clearly distinguishing them to avoid accidental divergence or confusion.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Since encode_to_b64/decode_from_b64 were renamed to encode/decode, consider keeping lightweight backward-compatible aliases (or a deprecation layer) to avoid breaking existing consumers of the encoder API.
- CUSTOM_BASE64_ALPHABET and X3_BASE64_ALPHABET currently have identical values; consider reusing a single constant or clearly distinguishing them to avoid accidental divergence or confusion.
## Individual Comments
### Comment 1
<location> `src/xhshow/utils/encoder.py:96-101` </location>
<code_context>
+ raise ValueError("Invalid Base64 input: unable to decode string") from e
+ return decoded_bytes
+
+ def encode_x3(self, input_bytes: bytes | bytearray) -> str:
+ """
+ Encode x3 signature using X3_BASE64_ALPHABET
+
+ Args:
+ input_bytes: Input byte data
+
+ Returns:
+ str: Base64 encoded string with X3 custom alphabet
+
+ Raises:
+ ValueError: Base64 encoding failed
+ """
+ try:
+ standard_encoded_bytes = base64.b64encode(input_bytes)
+ standard_encoded_string = standard_encoded_bytes.decode("utf-8")
+ except (binascii.Error, ValueError) as e:
+ raise ValueError("Failed to encode to Base64") from e
+
</code_context>
<issue_to_address>
**suggestion:** The try/except around base64.b64encode is likely unnecessary and may obscure unexpected errors.
Given the type hints (bytes | bytearray), base64.b64encode should not realistically raise binascii.Error or ValueError. Catching these broadly and re-raising a generic ValueError can hide programming errors if an unexpected type is passed. Consider removing this try/except, or only using error handling on the decode_x3 path where invalid external input is expected.
```suggestion
standard_encoded_bytes = base64.b64encode(input_bytes)
standard_encoded_string = standard_encoded_bytes.decode("utf-8")
```
</issue_to_address>
### Comment 2
<location> `src/xhshow/config/config.py:18-23` </location>
<code_context>
STANDARD_BASE64_ALPHABET = (
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
)
CUSTOM_BASE64_ALPHABET = (
"ZmserbBoHQtNP+wOcza/LpngG8yJq42KWYj0DSfdikx3VT16IlUAFM97hECvuRX5"
)
- BASE58_BASE = 58 # Base58 radix
- BYTE_SIZE = 256 # Byte size (2^8)
+ X3_BASE64_ALPHABET = (
+ "ZmserbBoHQtNP+wOcza/LpngG8yJq42KWYj0DSfdikx3VT16IlUAFM97hECvuRX5"
+ )
</code_context>
<issue_to_address>
**suggestion:** CUSTOM_BASE64_ALPHABET and X3_BASE64_ALPHABET duplicate the same literal, which risks drift.
Since they currently share the exact same string, consider defining one constant in terms of the other (e.g., X3_BASE64_ALPHABET = CUSTOM_BASE64_ALPHABET) to avoid future drift. If they’re intended to differ conceptually, giving X3_BASE64_ALPHABET a distinct value now would make that clearer.
```suggestion
CUSTOM_BASE64_ALPHABET = (
"ZmserbBoHQtNP+wOcza/LpngG8yJq42KWYj0DSfdikx3VT16IlUAFM97hECvuRX5"
)
# X3_BASE64_ALPHABET currently uses the same alphabet as CUSTOM_BASE64_ALPHABET.
# Defining it in terms of CUSTOM_BASE64_ALPHABET avoids duplication and drift.
X3_BASE64_ALPHABET = CUSTOM_BASE64_ALPHABET
```
</issue_to_address>
### Comment 3
<location> `tests/test_crypto.py:49-52` </location>
<code_context>
- # 验证Base58字符
- for char in result:
- assert char in self.crypto.config.BASE58_ALPHABET
+ # Base58已移除,此测试不再需要
+ pass
def test_base64_encoder(self):
</code_context>
<issue_to_address>
**suggestion (testing):** Repurpose or remove this test instead of leaving a no-op for removed Base58 functionality.
Leaving this as a `pass` is misleading and adds no value now that Base58 is gone. Please either delete the test or repurpose it to cover the new Base64 x3 behavior (e.g., round-trip encode/decode via `Base64Encoder.encode_x3`/`decode_x3`, and/or asserting the encoded x3 output only uses characters from `config.X3_BASE64_ALPHABET`). This will maintain coverage for the new encoding path that replaced Base58.
```suggestion
def test_base64_x3_encoder(self):
"""测试自定义Base64 x3 编码"""
test_string = "Hello, World!"
# 编码
encoded = self.crypto.b64encoder.encode_x3(test_string)
# 基本属性检查
assert isinstance(encoded, str)
assert len(encoded) > 0
# 校验只包含自定义X3 Base64字符表中的字符
for char in encoded:
assert char in self.crypto.config.X3_BASE64_ALPHABET
# 解码并验证与原始字符串一致
decoded = self.crypto.b64encoder.decode_x3(encoded)
assert decoded == test_string
```
</issue_to_address>
### Comment 4
<location> `tests/test_crypto.py:57` </location>
<code_context>
"""测试自定义Base64编码"""
test_string = "Hello, World!"
- result = self.crypto.b64encoder.encode_to_b64(test_string)
+ result = self.crypto.b64encoder.encode(test_string)
assert isinstance(result, str)
</code_context>
<issue_to_address>
**suggestion (testing):** Extend Base64 tests to cover roundtrip encode/decode and invalid input for the renamed methods.
The test now calls `encode`, but it only asserts success and the alphabet. Please also:
- Add a roundtrip check using `self.crypto.b64encoder.decode(result)` and assert it equals the original `test_string`.
- Add a test that `decode` raises `ValueError` for clearly invalid Base64 input (e.g., bad padding or invalid characters).
This will better cover the renamed API and its error handling paths.
Suggested implementation:
```python
def test_base64_encoder(self):
"""测试自定义Base64编码"""
test_string = "Hello, World!"
# 调用重命名后的 encode 方法
result = self.crypto.b64encoder.encode(test_string)
# 结果应为字符串
assert isinstance(result, str)
# 编解码回原始字符串
decoded = self.crypto.b64encoder.decode(result)
assert decoded == test_string
def test_base64_decoder_invalid_input(self):
"""测试Base64解码对非法输入的异常处理"""
# 明显非法的Base64字符串(包含非法字符和错误的填充)
invalid_inputs = [
"!!!not_base64!!!",
"abcd=", # 错误填充
"ab=c", # 非法字符
"YWJj*", # 非法字符
]
for invalid in invalid_inputs:
with pytest.raises(ValueError):
self.crypto.b64encoder.decode(invalid)
```
1. 确保本测试文件顶部已经导入 `pytest`,例如:`import pytest`。如果尚未导入,需要在文件头部添加对应的 `import`。
2. 此修改假设 `self.crypto.b64encoder.decode` 对非法 Base64 输入会抛出 `ValueError`。如果实际实现抛出的是其他异常类型,需要将 `pytest.raises(ValueError)` 中的异常类型调整为实际的异常类型。
</issue_to_address>
### Comment 5
<location> `tests/test_crypto.py:56-65` </location>
<code_context>
-
- assert isinstance(result, str)
- assert len(result) > 0
- # 验证Base58字符
- for char in result:
- assert char in self.crypto.config.BASE58_ALPHABET
</code_context>
<issue_to_address>
**suggestion (testing):** Update signature tests to validate the new Base64 x3 encoding and decoding behavior.
We removed the Base58-specific assertion in `test_build_signature`, but we’re not yet asserting anything about the new Base64/x3 behavior. To keep coverage equivalent after the refactor, please:
- In `test_build_signature`, assert that the returned signature:
- Has the expected prefix when applicable (e.g., if any higher-level method adds `config.X3_PREFIX`).
- Contains only characters from `self.client.crypto_processor.config.X3_BASE64_ALPHABET`.
- Add targeted tests for `decode_x3` to cover:
- A prefixed x3 signature that round-trips through `_build_signature` + `decode_x3` (after XOR), confirming the original payload bytes are recovered.
- A non-prefixed x3 signature to verify the "prefix optional" contract.
- An invalid x3 string (bad alphabet or invalid Base64) that results in the expected `ValueError` from `Base64Encoder.decode_x3`.
This will ensure the Base58→Base64 x3 migration is correctly exercised by tests and the `decode_x3` contract is enforced.
Suggested implementation:
```python
def test_base58_encoder(self):
"""测试Base58编码"""
# Base58已移除,此测试不再需要
pass
def test_base64_encoder(self):
"""测试自定义Base64编码 (x3 Base64)"""
test_string = "Hello, World!"
result = self.crypto.b64encoder.encode(test_string)
# 返回值类型应该为字符串
assert isinstance(result, str)
# 签名不能为空
assert len(result) > 0
# 验证x3前缀及Base64字符
config = self.crypto.config
# 如果启用了前缀,则结果应以X3_PREFIX开头
if getattr(config, "X3_PREFIX", None):
if result.startswith(config.X3_PREFIX):
core = result[len(config.X3_PREFIX) :]
else:
# 如果结果未带前缀,则整个结果视为核心编码
core = result
else:
core = result
# 所有字符必须在x3 Base64字母表中
alphabet = config.X3_BASE64_ALPHABET
for ch in core:
assert ch in alphabet
def test_decode_x3_round_trip_with_prefix(self):
"""测试带前缀的x3签名: _build_signature + decode_x3 之后恢复原始payload"""
# 原始payload使用字节串, 与签名逻辑保持一致
payload = b"test payload for x3 with prefix"
xor_key = 0x42 # 任意非零的XOR key, 与生产/实现保持一致
# 通过签名构建方法生成带前缀的x3签名
# 这里假设crypto上有生成签名的方法, 名称按当前实现调整
signature = self.crypto._build_signature(payload, xor_key=xor_key, with_prefix=True)
config = self.crypto.config
# 确认签名具有预期前缀
assert signature.startswith(config.X3_PREFIX)
# 通过decode_x3解码 (内部会处理前缀 + XOR)
decoded = self.crypto.b64encoder.decode_x3(signature, xor_key=xor_key)
# 解码后应恢复为原始payload
assert isinstance(decoded, (bytes, bytearray))
assert decoded == payload
def test_decode_x3_round_trip_without_prefix(self):
"""测试不带前缀的x3签名: 前缀可选, 仍然可以正确解码"""
payload = b"test payload for x3 without prefix"
xor_key = 0x24
# 生成不带前缀的x3签名
raw_x3 = self.crypto.b64encoder.encode_x3(payload, xor_key=xor_key, with_prefix=False)
config = self.crypto.config
# 确认没有X3前缀
assert not raw_x3.startswith(config.X3_PREFIX)
# decode_x3 应该支持无前缀输入
decoded = self.crypto.b64encoder.decode_x3(raw_x3, xor_key=xor_key)
assert isinstance(decoded, (bytes, bytearray))
assert decoded == payload
def test_decode_x3_invalid_string_raises_value_error(self):
"""测试无效x3字符串时, Base64Encoder.decode_x3 抛出 ValueError"""
config = self.crypto.config
# 构造包含非法字符的x3字符串:
# - 使用合法前缀
# - 在核心部分注入不在X3_BASE64_ALPHABET中的字符
bad_char = "!" # 一般不会在Base64字母表中
assert bad_char not in config.X3_BASE64_ALPHABET
invalid_core = "AAAA" + bad_char + "BBBB"
invalid_x3 = f"{config.X3_PREFIX}{invalid_core}"
xor_key = 0x01
# decode_x3 遇到非法字符应抛出 ValueError
with pytest.raises(ValueError):
self.crypto.b64encoder.decode_x3(invalid_x3, xor_key=xor_key)
```
1. 上面的实现假设:
- `self.crypto` 暴露:
- `config.X3_PREFIX`
- `config.X3_BASE64_ALPHABET`
- 方法 `_build_signature(payload: bytes, xor_key: int, with_prefix: bool = True) -> str`
- `b64encoder.encode_x3(payload: bytes, xor_key: int, with_prefix: bool = True) -> str`
- `b64encoder.decode_x3(x3: str, xor_key: int) -> bytes`
如果你们当前API命名不同,请将 `_build_signature` / `encode_x3` / `decode_x3` 和参数名调整为实际实现。
2. 文件中还需要更新 `test_build_signature`:
- 使用 `signature = self.crypto._build_signature(...)` 或对应的签名方法。
- 若签名应始终带前缀, 断言 `signature.startswith(self.crypto.config.X3_PREFIX)`。
- 针对签名主体(去掉前缀后)逐字符断言 `in self.crypto.config.X3_BASE64_ALPHABET`,替换掉原来的 Base58 字母表断言。
3. 如果你们的测试用例类当前没有 `pytest` 导入, 需要在 `tests/test_crypto.py` 顶部添加 `import pytest`。
4. 若XOR key的来源固定在配置/常量(而不是测试中硬编码), 请将测试中的 `xor_key` 调整为与生产逻辑一致的值或从配置中读取。
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Fixes #64
Summary by Sourcery
将签名处理从自定义 Base58 迁移到自定义 Base64 编码,并扩展 Base64 编码器以支持 x3 签名。
New Features:
Bug Fixes:
Enhancements:
Tests:
Original summary in English
Summary by Sourcery
Migrate signature handling from custom Base58 to custom Base64 encoding and extend the Base64 encoder for x3 signatures.
New Features:
Bug Fixes:
Enhancements:
Tests: