最近peazip这款压缩软件似乎有点热度,原因是除了传统密码加密之外,还能够添加使用文件作为密钥,能有效防止分享的资源被在线解压从而被和谐。我想,使用这个软件的文件密钥加密功能,可能会成为未来分享文件的一种趋势。而我最近开发的f-keydle,一款专门解多层压缩包的软件,我觉得势必也要支持解压由peazip这种加密方式创建而来的压缩包,这就是我研究如何将peazip的文件密钥加密模式转换为明文密码的原因。
其实我从好几个月之前就开始研究这个了,当时甚至已经从官网翻到了有关文件密钥转文字密钥的方法,链接和截图。
https://peazip.github.io/extract-encrypted-files.html
我之前没发现规律前的理解是,先把文件的sha256得到,然后把显示出来的结果(显示出的字符串)编码为base64放在前面作为文件那部分对应的密码,然后如果有额外添加的密码的话,把密码拼接在后面,这样就得到了一整段密码。然而,经过好几次尝试,均以密码不正确告终,我甚至猜测了密码前面有什么类似“filekey=”之类的前缀,或者sha256显示的大小写,或者说因为base64三个一组编码的特性,可能sha256最后会补上几个空格、0、下划线来凑成3的倍数后再编码为base64等等这些情况,不过这些尝试也宣告失败了。
我想自己暂时没有能力搞定这件事了,这件事于是被搁置了几个月,直到f-keydle的2.1版本更新,我在帖子里写出了这个想支持peazip的想法,帖子发出后出乎意料的得到了站里大佬@风之暇想 的回复,说是看的机器翻译说是先把文件转换成base64,然后再取sha256的值,看到后我就准备再尝试一下,用了个很小的文件作为密钥加密压缩包,然后使用在线工具进行转换,同样地,也似乎在意料中地失败了。
不过,这次站里大佬的回复给了我一点信心,我的好运气似乎也就这样来了。收到回复后差不多一两天,突破口就来了,我无意中点开了peazip的“控制台”选项卡,然后看到了一堆7z的命令,于是想到了之前看过的7z的命令行里,“-p”的后面是接密码的,于是眼光落在了那个区域,如下图被鼠标选中变蓝的区域:
于是把那部分密码复制了去解码,结果得到了一堆乱码,只有几个可见的字符:
emmm,不管怎么说先把之前-p后面的密码复制下来再说吧,先反过来把文件的sha256编码成base64试试,放在一起对比看看有什么规律:
乍一看似乎没有什么规律,还一短一长,但是光标放在一行的末尾,看到列数的时候,就发现了一个重要信息:
记事本光标放到一行文字开头,显示的是第1列,也就是说第一行peazip生成的密码有44个字符,而第二行从文件sha256显示的结果编码而来的有88个字符,正好是个两倍的关系。一个文件的sha256不管怎么说,显示出的结果的位数都是固定的,编码出的base64位数也该是一样的,怎么到了peazip这里就被砍半了呢?莫非peazip是两位一组?想到这里,回头看了看文件的sha256值:220f5398866623e40ce4bcc0f51f3744005cb56a8dd288c9c015b42e20a623e7 (上面的截图里也有),发现两位一组,似乎可以像winhex显示的那样,解读为单个字节对应的十六进制码。回到刚才解码显示出的一行乱码中,开头的英文双引号“ " ”对应的编码是U+0022,对应着sha256显示结果的第一组“22”;乱码里倒数第二个可见字符“ # ”对应的编码是U+0023,也对上了sha256显示结果的倒数第二组“23”,原来是这么转换文件sha256到base64的。至于额外添加的密码,后面我试着加了额外的密码,发现密码都是拼接在文件的base64后面的。
没想到规律就这么找到了,困扰我这么几个月的问题就在机缘巧合下就这么解决了,那叫一个开心啊,记得我当时激动地用力拍起了手。或许过去几个月我也看过那个“控制台”的窗口,或许也曾经想要试过将“-p”后面的密码找出些门道(我忘记有没有这么做过了),但是这一次的运气实在是太好了。说起来,我可能还要感谢@风之暇想 大佬带来的好运呢,哈哈。
规律找到后,接下来就是着手写软件了,也就是现在所分享的这个,下面是软件核心部分,转换文件到最终密码的代码:
[Python] 纯文本查看 复制代码
#计算sha256,推算出结果的进程函数
def calc_process(file_path:str) -> str:
#获取文件的sha256校验值(字符串)
h = hashlib.sha256()
f = open(file_path, 'rb')
while b := f.read(8192):
h.update(b)
f.close()
sha256_chars = h.hexdigest()
#把sha256校验值字符串看成十六进制的字节串(每两个字符为一个字节,就类似winhex显示的那样)进行转换
hex_bytes = bytes.fromhex(sha256_chars)
#把转换后的bytes编码成base64的bytes
base64_bytes = base64.b64encode(hex_bytes)
#解码为字符串
base64_string = base64_bytes.decode(encoding="utf-8")
return base64_string
如果有额外的密码,直接拼接在文件所对应的密码后面就行了,就不作展示了。
说是v1.0,其实软件在我手里已经迭代了好几个版本了,从最初的命令行窗口,到GUI窗口,制作每一次拖放后能自动清除上一次输入的文件路径的拖放窗口,以及后来为了解决处理大文件时界面卡死,在额外的线程或者进程里处理的功能,增加文件数据记忆和选择性删除文件记忆的功能等等,可谓是有点“费尽心思”,现在想到能提升的地方就是加个文件处理的进度条了,不过考虑到进度条实现起来很复杂,而且作为密钥的文件大多都是小文件,不需要等待很长时间,即使是2G大小的文件在我这也就是十几秒的功夫就处理完了,所以就没有加进度条。我想,对于我这个接触PyQt5不到一周的人来说,应该算是做得比较好了。
下面来介绍一下软件:
软件能在已知peazip中设定的密钥文件(可选)和密码(可选)的情况下,将peazip的这种双重验证加密模式,转换为可以被其他压缩软件识别的明文密码,进而无需安装peazip,即可解压由peazip的这种加密模式创建出来的压缩包(peazip自己的压缩包格式“PEA”除外)。
同样的,在加密压缩包时,也可以通过本软件选择密钥文件(可选)和密码(可选)。本软件据此生成明文密码后,用peazip外的其他压缩软件(用这个生成的明文密码)加密文件,加密后的文件反过来也支持在peazip中,通过设定密钥文件(可选)和密码(可选)的方式进行解压,或者依旧选择本软件生成明文密码进行解压。
总之,可以理解为peazip和其他解压软件是能够“互通”的,明文密码就是“互通”的桥梁,peazip和其他解压软件最终都是通过明文密码进行加密或解密压缩文件的(peazip自己的压缩包格式“PEA”除外),只不过peazip的明文密码是通过它自己的方式算出来的,现在知道了这个计算的过程和原理后,桥梁就算被打通了。
【软件特性】:
1.转换明文密码的计算过程会安排在新开的、单独的线程或进程中计算。文件大小 <= 20MB ,会直接在新开的独立线程中进行计算;文件大小 > 20MB ,将会在这个新开的独立线程中再开一个单独的进程进行计算,线程则负责给新开的进程传递参数和等待进程返回结果。这样的设定能保证软件的主线程,也就是界面,不会因为用来生成密钥的文件大小过大(几百MB甚至几个G朝上)而卡死。
2.每计算一个文件对应的密钥值,这个文件对应的密钥值就会被记录到内存中用于记忆(限制最多记忆100个),因此只要软件运行期间,第二次拖入同样路径下的文件时,程序会跳过读取文件和计算的步骤,直接从之前在内存的记录中调出这个文件对应的密钥值,这样可以大大加快重复使用大文件进行处理时的运行速度。如果想要强制对文件进行重新读取和处理,可以通过“清除当前文件记忆”按钮或者“清除全部文件记忆”按钮来清空这些记忆的文件和对应的密钥值。
3.鼠标悬停在任意按钮、输入框上等待一段时间,会跳出一行使用提示供参考。
哔哔了一堆,该放软件链接了:
https://wwkq.lanzouq.com/b01lms0ra
普通用户请下载下图所指的两个文件,“v1.0的使用演示.zip”解压后是使用教程
感兴趣的大佬可以研究一下源码:“Peazip文件密钥加密模式 - 转 - 明文密码(v1.0)【源码】.zip”
本程序github开源地址:
https://github.com/ssh-buanshishi/peazip_filekey_encryption_mode_to_plaintext_password
【软件截图】:
最后祝各位使用愉快!