czx*_*tkl 5 java encryption algorithm restful-url web-scraping
我计划在 LOL 中进行游戏数据挖掘,但一直停留在解析回放文件上。我发现最流行的重播记录器是 LOL Replay,它以 .lrf 文件记录游戏。它们保存为二进制文件。我尝试打印 lrf 文件以查找其中的一些模式。据我所知,该文件分为两部分:
\n\n最初的部分是元数据。它是人类可读的。最后,它显示了该 .lrf 文件的加密密钥(32 字节)和客户端哈希。
第二部分有几个部分。每个部分均采用“RESTful URL+加密+填充(可能)”格式。例如:
\n\n?S4GI____GET /observer-mode/rest/consumer/getGameDataChunk/EUW1/1390319411/1/token\n?S4GH____?\xef\xbf\xa5?G??,\\??1?q??"Lq}?n??&??????l??(?^P???\xef\xbf\xa5I?v??k>x??Z?\xef\xbf\xa1??3Gug\n......\n??6GI____GET /observer-mode/rest/consumer/getGameDataChunk/EUW1/1390319411/2/token\nRun Code Online (Sandbox Code Playgroud)\n\n有些甚至是不可读的字符。3
我已经关注了这个链接和这个维基。看起来他们在使用 GZIP 压缩内容后使用 BlowFish ECB 算法加上 PKCS5Padding 进行加密。但我无法使用元数据中的 32 字节加密密钥解密内容。而且我不确定应该从哪里开始阅读以及在哪里停止,因为 JVM 不断警告我Give Final block notproperly padded。
\n\n所以我的问题是:
\n\n任何帮助,将不胜感激。感谢你们。
\n\n根据 Divis 和 avbor 的回答,我尝试了以下 Java 片段来解码块:
\n\n // Decode EncryptKey with GameId\n byte[] gameIdBytes = ("502719605").getBytes();\n SecretKeySpec gameIdKeySpec = new SecretKeySpec(gameIdBytes, "Blowfish");\n Cipher gameIdCipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");\n gameIdCipher.init(Cipher.DECRYPT_MODE, gameIdKeySpec);\n byte[] encryptKeyBytes = Base64.decode("Sf9c+zGDyyST9DtcHn2zToscfeuN4u3/");\n byte[] encryptkeyDecryptedByGameId = gameIdCipher.doFinal(encryptKeyBytes);\n\n // Initialize the chunk cipher\n SecretKeySpec chunkSpec = new SecretKeySpec(encryptkeyDecryptedByGameId, "Blowfish");\n Cipher chunkCipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");\n chunkCipher.init(Cipher.DECRYPT_MODE, chunkSpec);\n\n byte[] chunkContent = getChunkContent();\n byte[] chunkDecryptedBytes = chunkCipher.doFinal(chunkContent);\nRun Code Online (Sandbox Code Playgroud)\n\n使用 gameid 解码加密密钥时,它不会出现错误。但是,它在最后两行中不起作用。目前,我只是硬编码 getChunkContent() 以返回一个包含两个 RESTful URL 之间的字节的字节数组。但 Java 要么返回“线程“主”javax.crypto.IllegalBlockSizeException 中的异常:使用填充密码解密时,输入长度必须是 8 的倍数”
\n\n或者
\n\n返回“线程“主”javax.crypto.BadPaddingException 中的异常:给定的最终块未正确填充”。
\n\n我注意到两个 RESTful URL 之间的十六进制模式如下:\n(第一个 URL 的十六进制,例如 /observer-mode/rest/consumer/getKeyFrame/EUW1/502719605/2/token) + 0a + (块内容) + 000000 +(下一个 URL 的十六进制)
\n\n我的问题是:
\n\n需要包含块的哪一部分?我需要在最后一个 URL 之后添加“0a”吗?我需要在下一个 URL 之前添加“000000”吗?
我是否使用了正确的填充算法(Blowfish/ECB/PKCS5Padding)?
我的测试 lrf 文件可以在以下位置下载:https://www.dropbox.com/s/yl1havphnb3z86d/game1.lrf
\n\n感谢迪维斯!使用上面的代码片段,我成功地解密了一些块信息,没有错误。当您编写自己的getChunkContent()时,有两件事值得注意:
\n\n块内容紧接在“hex for previous url 0a”之后开始。
当块内容的大小恰好达到 8 的倍数时,块内容将尽可能接近“0000000(下一个 url 的十六进制)”结束。
但我还有两个问题想问:
\n\n以下是我对两个 .../getKeyframe/... RESTful url 之间的内容进行解码的示例。
\n\n39117e0cc2f7e4bb1f8b080000000000000bed7d0b5c15d5 ... 7f23a90000\nRun Code Online (Sandbox Code Playgroud)\n\n根据此RFC 文档,我知道 Gzip 压缩数据以“1f8b08...”开头。我可以丢弃“39117e0cc2f7e4bb”并启动 gzip 解压缩后续内容吗?(其实我已经尝试过从“1f8b08..”开始解码了,至少可以解压不出错)
gzip 解压后,结果仍然是一长串二进制文件(带有一些可读的字符串,如召唤师名称、冠军名称等)。当我查看 wiki 时,它似乎还远未完成。我期望的是读取可读字符串中的每个项目、符文或动作。我究竟如何从中读取这些游戏事件?或者我们只是需要一些耐心来与社区一起解决这些问题?
数以百万计的感谢!
\n存储库开发贡献者在这里,根据 wiki,密钥是 base64 Blowfish ECB“加密密钥”(游戏 ID 作为 Blowfish 的密钥)。
然后,使用这个解密的密钥来解码内容(吹鱼ECB也是如此)。然后,gzip 解码。
base64decode encryptionkey = decodedKey
blowfishECBdecode decodedKey with (string) gameId as key = decodedKey
blowfishECBdecode content with decodedKey as key = decodedContent
gzipdecode decodedContent = binary
Run Code Online (Sandbox Code Playgroud)
我制作了一个库来下载和解码重播文件:https://github.com/EloGank/lol-replay-downloader并且CLI 命令也可用:https://github.com/EloGank/lol-replay-downloader- cli
希望它会有所帮助:)
| 归档时间: |
|
| 查看次数: |
3929 次 |
| 最近记录: |