feat: RSA login encryption + confirmed wechat type codes

Replace the Phase-0 placeholder password encryption with real RSA
(PKCS#1 v1.5). encrypt_password now builds an RSA public key from the
getSecureKey modulus/exponent (RSAPublicNumbers, e=int(hex,16),
n=int(hex,16)), encrypts the UTF-8 password, and returns hex (documented
assumption -- base64 is the one-line fallback noted in the docstring).
get_secure_key now returns the inner data dict to match the new contract;
pc_login keeps {account, password} with a comment on the username/password
and account/pwd fallbacks if pcLogin rejects.

Extend normalize_wechat_type with the Phase-0 confirmed codes:
2 -> image, 3 -> image_legacy, 4 -> video, 10 -> system (1 -> text and
-2 -> divider unchanged; 6/9/13/15/21/22 stay unknown until confirmed).

Tests:
- encrypt_password round-trip: generate an RSA keypair, build secure_key
  from its public numbers, encrypt, then decrypt with the private key and
  assert the original password comes back. Pins 512-hex output for a
  2048-bit key. No network.
- Parser parametrize table extended for the new codes (and a downstream
  message-fixture assertion updated from unknown -> image_legacy).

Suite: 87 -> 97 passing. ruff check clean.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-01 13:37:42 +08:00
parent 7f19b12e74
commit eebff9f786
7 changed files with 214 additions and 102 deletions
@@ -114,12 +114,12 @@ async def test_scrape_wechat_messages_drops_divider_and_paginates_backward():
assert r1["sender_head_url"] == "https://cdn.example.com/alice.png"
assert r1["raw_json"] == MESSAGE_RECORDS_PAGE1[0]
# m2 — image / chatroom / outgoing.
# m2 — image (legacy) / chatroom / outgoing.
assert r2["msg_id"] == "1000002"
assert r2["room_id"] == "room12345@chatroom"
assert r2["ori_talker"] == "room12345@chatroom"
assert r2["is_send"] == 1
assert r2["type"] == "unknown" # unmapped code passes through
assert r2["type"] == "image_legacy" # code 3 -> legacy image (phase0 §2)
assert r2["type_raw"] == 3 # raw image-type code preserved
assert r2["file_url"] == "https://cdn.example.com/img2.jpg"
assert r2["file_th_url"] == "https://cdn.example.com/img2_th.jpg"