200 lines
7.2 KiB
Python
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()
|