起因
某天,我的朋友在QQ上转发给我了一个带密码的Zip压缩包
我看了一眼,双击后默认用WinRAR打开了,然后复制粘贴密码:
啊?密码错误?
我第一反应当然是怀疑是不是对面冲多了手滑,在输密码的时候不小心多打了点什么进去,但是经过我们10分钟的友好交流后,他确定以及肯定自己绝对没有手滑,还把传给我的压缩包重新下载下来 在手机上 把密码粘贴进去成功解压了。
我当时眉头一紧,立马感觉到自己似乎站到了坑的边缘。
试图复现:
这里以我常用的文件管理器MiXplorer为例:
新建一个Zip压缩包,密码这里MiXplorer正常情况下只允许输入英文+数字,但我们可以直接把中文密码粘贴进去:
然后在手机上测试解压:
显然,是可以正常解压的,然后我们把这个压缩包传到电脑上(Win10)再次进行尝试:
原因分析:
不用多想,一定是编码的问题,但我很好奇,为什么会这样?以及原来的密码究竟被编码成了什么?
首先,我们Google搜索java zip 中文密码
,通过查找可以得知一个包:zip4j
然后我们写一小段代码来试着解压它:
1 | package main; |
运行,直接报错:
1 | Exception in thread "main" net.lingala.zip4j.exception.ZipException: Wrong password! |
搜索得知安卓默认中文编码是UTF-8,然后在翻阅zip4j的文档,可以发现这样一个方法:setUseUtf8CharsetForPasswords 我们修改代码如下:
1 | package main; |
这次能成功运行了。
运行是成了,但是为什么?通过方法名搜索我们找到了这样一个issue:https://github.com/srikanth-lingala/zip4j/issues/328
1 | Using non-ascii characters for passwords is in a grey zone as far as zip specification is concerned. Some tools convert passwords to utf8 and some don't. With the change that you linked, zip4j converts the password to utf8 by default, and I guess Windows doesn't, and that's why it works fine in your case when you revert the utf8 conversion. |
意思大概是zip4j在遇到中文密码的时候会先把密码转UTF-8,但是windows不会。这解决了我第一个疑问,下面我们来研究第二个问题:原来的密码究竟被编码成了什么?
密码便乘变成什么样了?
我们直接翻阅zip4j的源代码:
src/main/java/net/lingala/zip4j/ZipFile.java
1 | public void setUseUtf8CharsetForPasswords(boolean useUtf8CharsetForPasswords) { |
继续跟:
src/main/java/net/lingala/zip4j/crypto/StandardDecrypter.java
1 | private void init(byte[] headerBytes, char[] password, long lastModifiedFileTime, long crc, |
继续:
src/main/java/net/lingala/zip4j/crypto/engine/ZipCryptoEngine.java
1 | public void initKeys(char[] password, boolean useUtf8ForPassword) { |
来了:
src/main/java/net/lingala/zip4j/util/Zip4jUtil.java
1 | public static byte[] convertCharArrayToByteArray(char[] charArray, boolean useUtf8Charset) { |
我们把这段代码复制下来,然后再找一段将输出转为HEX的代码,组合起来试着运行看看:
1 | package main; |
输出:
1 | 克拉拉 |
好,那么这个4B C9 C9
是个什么东西?
我们打开winhex,直接打进去看看:
好,复制粘贴到WinRAR:
好,完工,又是涨奇怪知识的一天。
- 本文作者: Disappear9
- 本文链接: https://thinkalone.win/chinese-zip-password.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!