ksjsb/tests/test_h5_kww_alg.py
2026-07-30 20:25:56 +08:00

200 lines
7.2 KiB
Python

import unittest
from core.h5_kww_alg import (
js_utf16_code_units,
kwf_aes_cbc_decrypt,
kwf_aes_cbc_encrypt,
kwf_base64_decode_bytes,
kwf_base64_encode_bytes,
kwf_default_fingerprint_fields,
kwf_encrypt_fingerprint_hex,
kwf_fingerprint_plain,
kwf_generate_kww,
kwf_pack_fingerprint_fields,
kwf_insert_version_fields,
kwf_pack_fingerprint_plain,
kwf_mixer_char,
kwf_mixer_permutation,
kwf_remove_version_fields,
kwf_string_encoder_binary,
kwf_string_encoder_bytes,
)
class H5KwwAlgTests(unittest.TestCase):
def test_js_utf16_code_units_match_char_code_at(self):
self.assertEqual(js_utf16_code_units("A"), [0x41])
self.assertEqual(js_utf16_code_units("\u4e2d"), [0x4E2D])
self.assertEqual(js_utf16_code_units("\U0001f600"), [0xD83D, 0xDE00])
def test_string_encoder_ascii(self):
self.assertEqual(kwf_string_encoder_bytes("ABC123"), b"ABC123")
def test_string_encoder_two_and_three_byte_units(self):
self.assertEqual(kwf_string_encoder_bytes("\u00e9").hex(), "c3a9")
self.assertEqual(kwf_string_encoder_bytes("\u4e2d").hex(), "e4b8ad")
def test_string_encoder_nul_uses_two_byte_branch(self):
self.assertEqual(kwf_string_encoder_bytes("\x00").hex(), "c080")
def test_string_encoder_non_bmp_uses_surrogate_units(self):
self.assertEqual(
kwf_string_encoder_bytes("\U0001f600").hex(),
"eda0bdedb880",
)
def test_binary_string_roundtrip_shape(self):
encoded = kwf_string_encoder_binary("\u00e9")
self.assertEqual([ord(ch) for ch in encoded], [0xC3, 0xA9])
def test_mixer_permutation_matches_vm_shuffle_slice(self):
self.assertEqual(kwf_mixer_permutation(4, 0.5), [2, 0, 3, 1])
def test_mixer_char_uses_shuffled_index_position(self):
key_grid = ["AB", "CD"]
self.assertEqual(kwf_mixer_char(key_grid, 0.5, 0, 0), "B")
self.assertEqual(kwf_mixer_char(key_grid, 0.5, 1, 0), "A")
self.assertEqual(kwf_mixer_char(key_grid, 0.5, 1, 1), "C")
def test_mixer_rejects_ragged_key_grid(self):
with self.assertRaises(ValueError):
kwf_mixer_char(["AB", "C"], 0.5, 0, 0)
def test_fingerprint_plain_uses_k1_to_k14_and_js_boolean_shape(self):
fields = {
"k1": "ua",
"k2": True,
"k3": False,
"k5": 123,
"k14": "tail",
"other": "ignored",
}
self.assertEqual(
kwf_fingerprint_plain(fields),
"ua|1|0||123|||||||||tail",
)
def test_insert_version_fields_matches_tail_slice(self):
self.assertEqual(
kwf_insert_version_fields("0123456789ABCDEfgh", "A", "K"),
"0123456789AABCDEKfgh",
)
def test_remove_version_fields_reverses_tail_slice(self):
packed = kwf_insert_version_fields("0123456789ABCDEfgh", "A", "K")
self.assertEqual(kwf_remove_version_fields(packed), ("0123456789ABCDEfgh", "A", "K"))
def test_base64_encoder_uses_kwf_alphabet_and_padding(self):
self.assertEqual(kwf_base64_encode_bytes(b""), "")
self.assertEqual(kwf_base64_encode_bytes(b"\x00"), "ZZ==")
self.assertEqual(kwf_base64_encode_bytes(b"\x00\x00"), "ZZZ=")
self.assertEqual(kwf_base64_encode_bytes(b"ABC"), "cLQe")
def test_base64_decoder_inverts_kwf_alphabet(self):
self.assertEqual(kwf_base64_decode_bytes(""), b"")
self.assertEqual(kwf_base64_decode_bytes("ZZ=="), b"\x00")
self.assertEqual(kwf_base64_decode_bytes("ZZZ="), b"\x00\x00")
self.assertEqual(kwf_base64_decode_bytes("cLQe"), b"ABC")
def test_encrypt_fingerprint_hex_matches_deterministic_kwf_trace(self):
plain = "1|0.0.2|zh-CN|0|0|1|1|1|0|60|508|1780000000123|1|"
self.assertEqual(
kwf_encrypt_fingerprint_hex(plain),
"1f27caf6e5b260b2ff26f7ff5e19a03c"
"17a858350d7c3328507a9dd3d0e8fdee"
"5afd59d51e564481fb31c2ded4579fde"
"c8118956fdf90148ba78a52b1f4e01cb",
)
def test_aes_cbc_decrypt_reverses_node_crypto_sample(self):
cipher = bytes.fromhex(
"d60080e8511541d575cfe839fce1cf14742148fb5f79f85e"
"d79f42b2cb000d7e3657641f599dc66c7a04ff8fd01cb5fa"
"62f438b4724bf6232045049540d05bc601fb31f4a95a4e66"
"b7c98f1b8fc67731f2d5042d50939607fbc5028742cfec17"
)
plain = (
b'{"productName":"kuaishou-growth","ts":1780000000123,'
b'"did":"ANDROID_0123456789abcdef"}'
)
self.assertEqual(
kwf_aes_cbc_decrypt(
cipher,
key=b"webweaponconfigs",
iv=b"webweaponconfigs",
),
plain,
)
self.assertEqual(
kwf_aes_cbc_encrypt(
plain,
key=b"webweaponconfigs",
iv=b"webweaponconfigs",
),
cipher,
)
def test_pack_fingerprint_plain_matches_deterministic_kwf_trace(self):
plain = "1|0.0.2|zh-CN|0|0|1|1|1|0|60|508|1780000000123|1|"
self.assertEqual(
kwf_pack_fingerprint_plain(plain),
"PnGU+9+Y8008S+nH0U+0mjPf8fP08f+98f+nLlwnrIP9Pl+9rh+"
"/WA+/mD+9PAPAHh+/Z7G/SD8e+DPBLh8fzS8/pY8fcMwncMPnLM+"
"0cFwebfG0PlGAQD8ncF+/qE8fzSGAWlP/WE+/8f8BGEPerFwBQY+"
"AYY+/QjPnGF8/ZlG9H=",
)
def test_pack_fingerprint_fields_matches_deterministic_kwf_trace(self):
fields = {
"k1": 1,
"k2": "0.0.2",
"k3": "zh-CN",
"k4": "0",
"k5": False,
"k6": True,
"k7": True,
"k8": "1",
"k9": "0",
"k10": 60,
"k11": 508,
"k12": 1780000000123,
"k13": "2",
"k14": "",
}
self.assertEqual(
kwf_pack_fingerprint_fields(fields),
"PnGU+9+Y8008S+nH0U+0mjPf8fP08f+98f+nLlwnrIP9Pl+9rh+"
"/WA+/mD+9PAPAHh+/Z7G/SD8e+DPBLh8fzS8nPhwB+DP0D9G0S0G"
"9zSGnpS8nrUP9rh+0qEweDE+0WM+9bf80QSw/rl+0GUGAcl+AqF+"
"ASSwnLI+9c7+BG7GnL=",
)
def test_generate_kww_matches_first_two_deterministic_trace_values(self):
first = kwf_generate_kww(collect_count=1, now_ms=1780000000123)
second = kwf_generate_kww(collect_count=2, now_ms=1780000000123)
self.assertEqual(first[:87], second[:87])
self.assertEqual(
first,
"PnGU+9+Y8008S+nH0U+0mjPf8fP08f+98f+nLlwnrIP9Pl+9rh+"
"/WA+/mD+9PAPAHh+/Z7G/SD8e+DPBLh8fzS8/pY8fcMwncMPnLM+"
"0cFwebfG0PlGAQD8ncF+/qE8fzSGAWlP/WE+/8f8BGEPerFwBQY+"
"AYY+/QjPnGF8/ZlG9H=",
)
self.assertEqual(
second,
"PnGU+9+Y8008S+nH0U+0mjPf8fP08f+98f+nLlwnrIP9Pl+9rh+"
"/WA+/mD+9PAPAHh+/Z7G/SD8e+DPBLh8fzS8nPhwB+DP0D9G0S0G"
"9zSGnpS8nrUP9rh+0qEweDE+0WM+9bf80QSw/rl+0GUGAcl+AqF+"
"ASSwnLI+9c7+BG7GnL=",
)
def test_default_fingerprint_fields_keep_empty_k14(self):
fields = kwf_default_fingerprint_fields(collect_count=1, now_ms=1780000000123)
self.assertEqual(fields["k14"], "")
self.assertEqual(fields["k13"], "1")
if __name__ == "__main__":
unittest.main()