带有特殊字符的python 7z密码

时间:2014-02-06 18:43:24

标签: python unzip 7zip

我试图用7z.exe解压缩文件,密码中包含特殊字符

EX。 &)kra932(lk0¤23

执行以下命令:

subprocess.call(['7z.exe', 'x', '-y', '-ps^&)kratsaslkd932(lkasdf930¤23', 'file.zip'])

7z.exe启动正常,但它说密码错误。

这是我创建的文件,它让我疯狂。

如果我在Windows命令行上运行该命令,则运行正常

7z.exe x -y -ps^&)kratsaslkd932(lkasdf930¤23 file.zip

如何让python转义为&字符?


@Wim问题发生了&在密码上,因为我执行时

7z.exe x -y -ps^&)kratsaslkd932(lkasdf930¤23 file.zip 

它表示无效的命令')kratsaslkd932(lkasdf930¤23' 即时通讯使用python 2.76,由于只运行在2.76

的公司工具,无法升级到3.x.

3 个答案:

答案 0 :(得分:0)

我建议使用原始字符串和shlex模块(特别是在Windows上),不支持ASCII以外的任何编码。

import shlex
import subprocess

cmd = r'7z.exe x -y -p^&moreASCIIpasswordchars file.zip'
subprocess.call(shlex.split(cmd))

回到非ASCII字符问题......

我非常确定Python版本< 3你根本不能使用非ASCII字符。我不是C专家,但请注意2.73.3之间的区别。前者使用“标准”字符,而后者使用宽字符。

答案 1 :(得分:0)

请尝试在密码之间加上双引号,否则cmd解析器将按原样解析特殊字符,而不是将其作为密码的一部分。

例如, /** * Responds to any HTTP request. * * @param {!express:Request} req HTTP request context. * @param {!express:Response} res HTTP response context. */ exports.helloWorld = (req, res) => { let message = req.query.message || req.body.message || 'Hello World!'; console.log('Headers from request: ' + JSON.stringify(req.headers)); let parsedBody; if(req.header('content-type') === 'application/json') { console.log('request header content-type is application/json and auto parsing the req body as json'); parsedBody = req.body; } else { console.log('request header content-type is NOT application/json and MANUALLY parsing the req body as json'); parsedBody = JSON.parse(req.body); } console.log('Message from parsed json body is:' + parsedBody.message); res.status(200).send(message); }; 不起作用。

但是7z.exe x -y -ps^&)kratsaslkd932(lkasdf930¤23 file.zip肯定可以。

答案 2 :(得分:0)

在命令行上传递密码存在很大的安全风险。具有管理权限,可以检索该信息(启动信息对象)并提取密码。更好的解决方案是将7zip作为一个进程打开,并将密码输入其标准输入中。

这是一个命令行示例,它将“ source.txt”压缩为“ dest.7z”:

CMD = ['c:\\Program Files\\7-Zip\\7z.exe', 'a', '-t7z', '-p', 'c:\\source.txt', 'd:\\dest.7z']
PASSWORD = "Nj@8G86Tuj#a"

首先,您需要将密码转换为输入字符串。请注意,7-zip要求在终端输入密码。您可以使用特殊字符,只要它们可以在终端中显示即可。终端的编码很重要!例如,在匈牙利语Windows上,您可能要使用“ cp1250”编码。在所有情况下,标准输入都是二进制文件,并且期望二进制字符串(Python 3中为“字节”)。为了安全起见,可以将密码限制为纯ascii并按以下方式创建输入:

input = (PASSWORD + "\r\n").encode("ascii")

如果您知道终端的编码,则可以将密码转换为该编码。您还将能够检测密码是否不能与系统的编码一起使用。 (顺便说一句,这也意味着它也不能交互使用。)

(上次我检查过,Windows上不同区域设置的终端编码是不同的。也许有技巧将其更改为UTF-8,但我不确定如何。)

这是执行命令的方式:

import subprocess
import typing

def execute(cmd : typing.List[str], input: typing.Optional[bytes] = None, verbose=False, debug=False, normal_priority=False):
    if verbose:
        print(cmd)
    creationflags = subprocess.CREATE_NO_WINDOW
    if normal_priority:
        creationflags |= subprocess.NORMAL_PRIORITY_CLASS
    else:
        creationflags |= subprocess.BELOW_NORMAL_PRIORITY_CLASS

    if debug:
        process = subprocess.Popen(cmd, shell=False, stdout=sys.stdout, stderr=sys.stderr, stdin=subprocess.PIPE,
                                   creationflags=creationflags)
    else:
        process = subprocess.Popen(cmd, shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
                                   stdin=subprocess.PIPE, creationflags=creationflags)
    if input:
        process.stdin.write(input)
        process.stdin.flush()
    returncode = process.wait()
    if returncode:
        raise OSError(returncode)


CMD = ['c:\\Program Files\\7-Zip\\7z.exe', 'a', '-t7z', '-p', 'c:\\source.txt', 'd:\\dest.7z']
PASSWORD = "Nj@8G86Tuj#a"
input = (PASSWORD + "\r\n").encode("ascii")
execute(CMD, input)

这还显示了如何降低进程优先级(压缩大量数据时通常是个好主意),并且还显示了如何将标准输出和标准错误转发到控制台。

绝对正确的解决方案是加载7-zip DLL并使用其API。 (我没有检查,但是可能可以使用8位二进制字符串作为密码。)

注意:此示例适用于Python 3,但使用Python 2也可以做到这一点。