算法暴露接口(xhs、dy、ks、wx、hnw)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
4.8 KiB

7 months ago
  1. import base64
  2. from xhs.shield_aes import get_key
  3. from xhs.shield_md5 import md5sum
  4. from xhs.shield_rc4 import RC4
  5. def hex_string(num, step=2):
  6. """
  7. step
  8. """
  9. tmp_string = hex(num)[2:]
  10. if len(tmp_string) < step:
  11. tmp_string = '0' + tmp_string
  12. return tmp_string
  13. def expand_keys(keys, m):
  14. md5_str1_list = [hex_string(int(keys[i] + keys[i + 1], 16) ^ m) for i in range(0, len(keys), 2)]
  15. md5_str1 = "".join(md5_str1_list)
  16. return md5_str1
  17. def char2hex(char):
  18. return hex_string(ord(char))
  19. def get_md5(keys, params):
  20. """
  21. hmac
  22. :param keys:
  23. :param params:
  24. :return:
  25. """
  26. # 拓展key1 0x36
  27. md5_str1 = expand_keys(keys, 54)
  28. # 拓展key2 0x5c
  29. md5_str2 = expand_keys(keys, 92)
  30. data = bytes.fromhex(md5_str1) + params.encode("utf-8")
  31. md1 = md5sum(data)
  32. data1 = bytes.fromhex(md5_str2 + md1)
  33. md2 = md5sum(data1) # 获得最终结果
  34. return md2
  35. def get_rc4(params):
  36. """
  37. rc4运算
  38. :param params:
  39. :return:
  40. """
  41. key = "std::abort();"
  42. result = RC4(key.encode("utf-8"), bytes.fromhex(params))
  43. return result.hex()
  44. def get_shield(keys, params, deviceId):
  45. """
  46. shield生成核心部分
  47. app_id
  48. :param keys:
  49. :param params:
  50. :param deviceId:
  51. :return:
  52. """
  53. version = "6970181"
  54. app_id = "ecfaaf01"
  55. p7 = "".join([char2hex(m) for m in version])
  56. p8 = "".join([char2hex(m) for m in deviceId])
  57. p9 = get_md5(keys, params) # 魔改md5 16位md5
  58. rc4_plaintext = f"00000001{app_id}00000002000000{hex_string(len(version))}000000{hex_string(len(deviceId))}000000{hex_string(len(p9) // 2)}{p7}{p8}{p9}"
  59. result = get_rc4(rc4_plaintext)
  60. _tmp = len(version) + len(deviceId) + len(p9) // 2 + 24
  61. tmp = f"0000000100000001000000{hex_string(_tmp)}000000{hex_string(_tmp)}" # 固定 0x53是上述 几个固定的值算出来的
  62. _shield = "XY" + base64.b64encode(bytes.fromhex(tmp + result)).decode()
  63. return _shield
  64. def shield(node_id, xy_common_params, xy_platform_info):
  65. """
  66. """
  67. # 设备一
  68. deviceId = "2fe75062-a528-3340-bed3-220a67f7f240"
  69. keys = "aa82da57410dddd5b2860e534f7c0602f589c20ec8e8830baa239360c89cce62bdc304d8a1aa988d620917dbefc2a1154692fad24294f4419ea19c7dc069897b"
  70. api = "/api/sns/v1/note/feed"
  71. param = f"note_id={node_id}&page=1&num=5&fetch_mode=1&source=&ads_track_id="
  72. plaintext = api + param + xy_common_params + xy_platform_info
  73. return get_shield(keys, plaintext, deviceId)
  74. def shield_run(url, keys, xy_common_params, deviceId, api="/api/sns/v1/note/feed"):
  75. """
  76. :param url:
  77. :param keys: hmac_main
  78. :param xy_common_params: header中字段
  79. :param deviceId:
  80. :param api: feed流接口
  81. :return:
  82. """
  83. param = url[url.index("?") + 1:]
  84. xy_platform_info = f"platform=android&build=6970181&deviceId={deviceId}"
  85. plaintext = api + param + xy_common_params + xy_platform_info
  86. # print(plaintext)
  87. return get_shield(keys, plaintext, deviceId)
  88. if __name__ == '__main__':
  89. # 先获得 main_hmac 处理后的key
  90. # XYAAAAAQAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+qCLOlKGmTtFa+lG43AHe+FXTKxDxI2yn7IxH534qbVaz8N7icV+2KNmRAwcQDSAZrqn3SpjhOCLuaGTuDRgbpA0sNhU/xUP 结果
  91. # XYAAAAAQAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+qCLOlKGmTtFa+lG43AHe+FXTKxDxI2yn7IxH534qbVaz8N7icV+2KNmRAwcQDSAZrqn3SpjhOCLuaGTuDRgbpA0sNhU/xUP
  92. # keys = "aa82da57410dddd5b2860e534f7c0602f589c20ec8e8830baa239360c89cce62bdc304d8a1aa988d620917dbefc2a1154692fad24294f4419ea19c7dc069897b"
  93. # get_shield(keys)
  94. url = "https://edith.xiaohongshu.com/api/sns/v1/note/feed?note_id=66ceeabe000000001d03b546&page=1&num=5&fetch_mode=1&source=&ads_track_id="
  95. hmac = "NqLx0YFKNb4KraYq524SgzVpepYQ0SwhZLRs7eyxe6A26c/b1b+d6OU2LfAPwh8zpt3fkR/jsR5yzVzIqXe66EWhGJ8iWV36KKSIz0mVt436sTqt3eUYUZwb5TzpSYDa"
  96. deviceId = "119214fc-0fe5-3ae8-91dd-baa821c11324"
  97. xy_platform_info = "platform=android&build=6970181&deviceId=119214fc-0fe5-3ae8-91dd-baa821c11324"
  98. xy_common_params = "fid=1721639154103483c0daaace2ca9266cba37ac9fe114&device_fingerprint=202407221758192809006e7e334e46628620f6768bcf3b0153b1977b9f6cd6&device_fingerprint1=202407221758192809006e7e334e46628620f6768bcf3b0153b1977b9f6cd6&cpu_name=Qualcomm+Technologies%2C+Inc+SM8150&device_model=phone&launch_id=1727578036&tz=Asia%2FShanghai&channel=CPA-3DSP-N3-ZSKJ&versionName=6.97.0.1&overseas_channel=0&deviceId=119214fc-0fe5-3ae8-91dd-baa821c11324&platform=android&sid=session.1721639201142076381131&identifier_flag=4&t=1727590998&project_id=ECFAAF&build=6970181&lang=zh-Hans&app_id=ECFAAF01&uis=dark&teenager=0"
  99. keys = get_key(deviceId, hmac)
  100. result = sheild_run(url, keys, xy_common_params, deviceId)
  101. print(result)