如何使用python gnupg模块vers进行对称加密。 1.2.5?

时间:2014-05-04 17:32:49

标签: python encryption gnupg

我正在尝试使用python和gnupg进行对称加密。

此代码段适用于我的windows vista机器,python gnupg模块的版本为0.3.2:

import gnupg
gpg = gnupg.GPG()
data = 'the quick brown fow jumps over the laxy dog.'
passphrase='12345'
crypt = gpg.encrypt(data, recipients=None,
                     symmetric='AES256',
                     passphrase=passphrase,
                     armor=False)

当我尝试使用版本1.2.5 python gnupg模块在我的linux机器上运行它时,我收到此错误:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "/usr/local/lib/python2.7/dist-packages/gnupg/gnupg.py", line 961, in encrypt
    result = self._encrypt(stream, recipients, **kwargs)
TypeError: _encrypt() got multiple values for keyword argument 'recipients'

我做了很多搜索,但在这方面找不到任何东西。

4 个答案:

答案 0 :(得分:4)

这是一个古老的问题,但我在谷歌搜索中发现了这一点,并对提供的答案感到不满。我在python-gnupg的GitHub问题中找到了真正的答案:

gpg.encrypt(data, symmetric='AES256', passphrase=passphrase, armor=False, encrypt=False)

因此,请删除recipients=None并添加encrypt=False。然后,您的crypt.data将包含加密数据。不直观,但它确实有效。

(src:https://github.com/isislovecruft/python-gnupg/issues/110

答案 1 :(得分:0)

仔细检查the documentation,参数不是recipient,是recipients(注意复数)

Docs(强调我的):

  

symmetric(默认为False)如果指定,则对称加密   用过的。在这种情况下,请将收件人指定为“无”。如果指定了True,   然后使用默认密码算法(CAST5)。从...开始   版本0.3.5,您还可以指定要使用的密码算法(for   例如,&#39; AES256&#39;)。检查你的gpg命令行帮助,看看是什么   支持对称密码算法。请注意默认值   (CAST5)可能不是最好的。

答案 2 :(得分:0)

这应该适用于python-gnupg 0.3.5及更高版本(根据需要进行调整):

import gnupg

gpg_home = "~/.gnupg"
gpg = gnupg.GPG(gnupghome=gpg_home)

data = raw_input("Enter full path of file to encrypt: ")
phrase = raw_input("Enter the passphrase to decrypt the file: ")
cipher = raw_input("Enter symmetric encryption algorithm to use: ")
savefile = data+".asc"

afile = open(data, "rb")
encrypted_ascii_data = gpg.encrypt_file(afile, None, passphrase=phrase, symmetric=cipher.upper(), output=savefile)
afile.close()

不确定0.3.5之前的版本。

当调用gpg.encrypt_file()时,收件人的“无”(当前版本的模块)不需要“recipients = None”。

答案 3 :(得分:0)

我认为它已经坏了(如果我错了,请纠正我)。对于Python 3.x,它似乎在gnupg 0.3.6-1中得到修复。您可能最好使用它或尝试解决方法,例如类似于我将要描述的解决方法。

此解决方法使用Python中的命令行gpg而不是gnupg模块。当然,您可以使用gpg.encrypt_file执行类似的解决方法(我不会在下一段中讨论临时存储的密码;这很可能是更好的选择。)

如果您担心任务管理器中出现的密码短语,我会将密码放在一个临时文件中并使用cat将其输入gpg来处理。但是,可能必须担心恶意软件会从临时文件中抢夺密码,如果可以及时执行此操作。

请注意,此代码在Python 3.x中,因为这是我最常用的(在2.x中重新创建它,您必须了解临时文件在其中的工作原理,并且可能其他一些事情)。

import subprocess, tempfile, os, shutil

def gpg_encrypt(data, passphrase, alg="AES256", hash="SHA512", compress_alg="BZIP2", compress_lvl="9", iterations="1000000"):
    #This is for symmetric encryption.
    with tempfile.TemporaryDirectory() as directory:
        filepath=os.path.join(directory, "tmp")
        with open(filepath, "w") as FILE:
            FILE.write(data)
        iterations=str(iterations)
        compress_level="--compress-level "+compress_lvl
        if compress_alg.upper()=="BZIP2":
            compress_level="--bzip2-compress-level "+compress_lvl
        tmp_filename="tmp"
        with tempfile.TemporaryDirectory() as DIR:
            tmpfilepath=os.path.join(DIR, tmp_filename)
            with open(tmpfilepath, "w") as FILE:
                FILE.write(passphrase)
            subprocess.Popen("cat "+tmpfilepath+"|gpg --batch --yes --passphrase-fd 0 --force-mdc --s2k-mode 3 --s2k-count "+iterations+" --s2k-cipher-algo "+alg+" --s2k-digest-algo "+hash+" --compress-algo='"+compress_alg+"' --compress-level "+compress_lvl+" -ac '"+filepath+"'", stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True).communicate()[0]
        result=None
        with open(filepath+".asc", "r") as FILE:
            result=FILE.read()
        return result

def gpg_decrypt(data, passphrase):
    #This is for decryption.
    with tempfile.TemporaryDirectory() as directory:
        filepath=os.path.join(directory, "tmp")
        with open(filepath, "w") as FILE:
            FILE.write(data)
        decrypted=None
        tmp_filename="tmp"
        with tempfile.TemporaryDirectory() as DIR:
            tmpfilepath=os.path.join(DIR, tmp_filename)
            with open(tmpfilepath, "w") as FILE:
                FILE.write(passphrase)
            decrypted=subprocess.Popen("cat "+tmpfilepath+"|gpg --batch --yes --passphrase-fd 0 --output='"+filepath+".gpg"+"' '"+filepath+"'", stdin=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
        result=None
        decrypted=not "decryption failed:" in str(decrypted)
        if decrypted==True:
            with open(filepath+".gpg", "r") as FILE:
                result=FILE.read()
    return decrypted, result #If it worked, return True. If not, return False. (And, return the decrypted data.)

test=gpg_encrypt(data="This is a test!", passphrase="enter")
print("Here is the encrypted message:\n"+test)
decrypted, data=gpg_decrypt(data=test, passphrase="enter")
if decrypted:
    print("Here is the decrypted message:\n"+data)
else:
    print("Incorrect passphrase to decrypt the message.")

这里是加密/解密对称加密文件的代码(仅用于衡量标准):

import subprocess, tempfile, os, shutil

def gpg_encrypt_file(filepath, passphrase, output=None, alg="AES256", hash="SHA512", compress_alg="BZIP2", compress_lvl="9", iterations="1000000"):
    #This is for symmetric encryption.
    filepath=filepath.replace("'", "'\\''") #This makes it so you can have apostrophes within single quotes.
    iterations=str(iterations)
    compress_level="--compress-level "+compress_lvl
    if compress_alg.upper()=="BZIP2":
        compress_level="--bzip2-compress-level "+compress_lvl
    result=None
    tmp_filename="tmp"
    with tempfile.TemporaryDirectory() as DIR:
        tmpfilepath=os.path.join(DIR, tmp_filename)
        with open(tmpfilepath, "w") as FILE:
            FILE.write(passphrase)
        if output:
            if output[0]!=os.sep and filepath[0]==os.sep:
                output=os.path.join(os.path.dirname(filepath), output)
            result=subprocess.Popen("cat "+tmpfilepath+"|gpg --batch --yes --passphrase-fd 0 --force-mdc --s2k-mode 3 --s2k-count "+iterations+" --s2k-cipher-algo "+alg+" --s2k-digest-algo "+hash+" --compress-algo='"+compress_alg+"' "+compress_level+" --output='"+output+"' -ac '"+filepath+"'", stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True).communicate()[0]
        else:
            result=subprocess.Popen("cat "+tmpfilepath+"|gpg --batch --yes --passphrase-fd 0 --force-mdc --s2k-mode 3 --s2k-count "+iterations+" --s2k-cipher-algo "+alg+" --s2k-digest-algo "+hash+" --compress-algo='"+compress_alg+"' --compress-level "+compress_lvl+" -ac '"+filepath+"'", stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True).communicate()[0]
    return result.strip()

def gpg_decrypt_file(filepath, passphrase, output=None):
    #This is for decryption.
    filepath=filepath.replace("'", "'\\''")
    result=None
    tmp_filename="tmp"
    with tempfile.TemporaryDirectory() as DIR:
        tmpfilepath=os.path.join(DIR, tmp_filename)
        with open(tmpfilepath, "w") as FILE:
            FILE.write(passphrase)
        if output:
            if output[0]!=os.sep and filepath[0]==os.sep:
                output=os.path.join(os.path.dirname(filepath), output)
            result=subprocess.Popen("cat "+tmpfilepath+"|gpg --batch --yes --passphrase-fd 0 --output='"+output+"' '"+filepath+"'", stdin=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
        else:
            result=subprocess.Popen("cat "+tmpfilepath+"|gpg --batch --yes --passphrase-fd 0 '"+filepath+"'", stdin=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
    return not "decryption failed:" in str(result) #If it worked, return True. If not, return False.

gpg_encrypt_file(filepath="test.txt", passphrase="myPassphrase", output="test.asc")
if gpg_decrypt_file(filepath="test.asc", passphrase="myPassphrase", output="output.txt"):
    print("Successfully decrypted!")
else:
    print("Incorrect passphrase.")