无法使用私钥解密Python-GNUPG加密文件

时间:2019-03-07 01:41:21

标签: python encryption gnupg

我正在尝试使用python-gnupg和客户端提供的公共密钥在Python 3.6中对文本文件进行加密,他们有一个专用密钥对其进行解密。我无权访问该密钥。尽管python-gnupg 出现成功加密了文件(尽管日志中出现了一些令人困惑的错误),但客户端无法解密它。我们被告知他们遇到的错误是gpg: decryption failed: No secret key

当我们测试使用Cryptophane(不同的计算机,运行Windows而不是Ubuntu)和相同的公钥对文件加密时,他们能够对其解密。这是手动成功加密几个月的方式。当使用 our 公司公钥测试相同的代码时,我们能够使用私钥和Cryptophane对其进行解密。

我已经在Google上广泛搜索了错误消息和一般问题,但没有发现任何似乎可以解决的相同问题。

这是相关的代码。 filepath是要加密文件的相对路径。 pgp_key_name是包含公钥的.asc文件的名称。 pgp_key_dir是它所在的目录。

def pgp_encrypt_file(filepath, pgp_key_name, pgp_key_dir):
    gpg = gnupg.GPG()

    output_full_filepath = filepath + '.pgp'

    try:
        with open(pgp_key_dir + pgp_key_name) as file:
            key_data = file.read()

        import_result = gpg.import_keys(key_data)
        logger.info(msg='Public key imported: {}'.format(pgp_key_name))

        public_keys = gpg.list_keys()
        fingerprint = public_keys[0]['fingerprint']

        logger.info(msg='Attempting to encrypt file: ' + 
                    output_full_filepath)
        with open(filepath, 'r') as f:
            newfile = f.read()

        status = gpg.encrypt(newfile, fingerprint, 
                            output=output_full_filepath)

        logger.info(msg='status.ok : ' + str(status.ok))
        logger.info(msg='status.status : ' + str(status.status))

    except FileNotFoundError as e:
        logger.error(msg='File not found: ' + str(e))
    except TypeError as e:
        logger.error(msg='GNUPG TypeError: ' + str(e))

    return output_full_filepath

以及日志的相关部分:

03-01 15:18:58 gnupg        INFO     Setting homedir to 
'/home/[user]/.config/python-gnupg'
03-01 15:18:58 gnupg        ERROR    Could neither invoke nor terminate a 
gpg process... Are you sure you specified the corrent (and full) path to the 
gpg binary?

(该错误稍后不再出现,我无法在Google或Stack Overflow上找到任何相关内容。)

03-04 09:04:39 gnupg        WARNING  Ignoring '/usr/bin/gpg' (path is a symlink)
03-04 09:04:39 gnupg        ERROR    Could not find binary for 'gpg'.
03-04 09:04:39 gnupg        INFO     Setting homedir to 
'/home/[user]/.config/python-gnupg'
03-04 09:04:39 gnupg        INFO
Initialised settings:
binary: /usr/bin/gpg2
binary version: `2.0.14\ncfg:pubkey:1;16;17\ncfg:cipher:2;3;4;7;8;9;10;11;12;13\ncfg:ciphername:3DES;CAST5;BLOWFISH;AES;AES192;AES256;TWOFISH;CAMELLIA128;CAMELLIA192;CAMELLIA256\ncfg:digest:1;2;3;8;9;10;11\ncfg:digestname:MD5;SHA1;RIPEMD160;SHA256;SHA384;SHA512;SHA224\ncfg:compress:0;1;2;3\n'
homedir: /home/[user]/.config/python-gnupg
ignore_homedir_permissions: False
keyring: /home/[user]/.config/python-gnupg/pubring.gpg
secring: /home/[user]/.config/python-gnupg/secring.gpg
default_preference_list: SHA512 SHA384 SHA256 AES256 CAMELLIA256 TWOFISH 
AES192 ZLIB ZIP Uncompressed
keyserver: hkp://wwwkeys.pgp.net
options: None
verbose: False
use_agent: False

03-04 09:04:39 gnupg        INFO     Importing: [first few lines of public key]
03-04 09:04:39 root         INFO     Public key imported: [name of key]
03-04 09:04:39 root         INFO     Attempting to encrypt file: [file]
03-04 09:04:39 gnupg        INFO     Writing encrypted output to file: 
[file.pgp]
03-04 09:04:39 gnupg        INFO     Encrypted output written successfully.

我们尝试过的一些想法和事情:

  1. 尽管/ usr / bin / gpg中有一个gpg二进制文件,但是我们为项目本身使用了一个conda虚拟环境,我认为这可能会弄乱它。但是,当我从命令行运行此代码并停用环境时,最终得到了相同的结果。 我看到该日志文件说它找不到gpg二进制文件,并且它忽略了指向它的符号链接,但是此后的所有状态消息似乎都表明加密是正确的,并且再次可以正常工作多次使用不同的公钥/私钥对。

  2. 实例化IDE中的pgp对象后,我认为即使没有将任何参数传递给gnupg.GPG(),它也发现gpg二进制文件很好。传递gnupghome='/usr/bin/gpg'会把我带到同一个地方,传递gnupghome='not/real/path会引发错误。

  3. 在对armor=False的呼叫上设置encrypt并没有任何改变。

我非常感谢对此事的所有想法。 如果答案是由于我们的虚拟环境设置而没有在gpg二进制文件或homedir的正确目录中查找,那么也将建议您解决该问题的方法。

2 个答案:

答案 0 :(得分:2)

已解决。

在这种情况下,这是客户端的错误。后来,我们尝试使用各种稍有不同的选项来加密文件,其中包括许多从命令行和Python完成的选项。 他们能够解密每一个。

为了帮助其他人,这是我从此旅程开始以来学到的一些东西:

  1. 有两个名为python-gnupg的两个不同的软件包

由于这些软件包共享一个名称,因此在一个或另一个中查询错误时,它们会非常混乱。进行pip install python-gnupg似乎总是下载第二个。我的经验几乎完全与第二篇有关,因此在阅读本文中的其他内容时请记住这一点。

  1. 在CentOS 6上,/usr/bin/gpg是指向/usr/bin/gpg2的符号链接。 Python-GNUPG记录了注意到这一点的错误,但随后似乎发现/usr/bin/gpg2很好。

  2. 关于错误Could neither invoke nor terminate a gpg process...:尽管这与我有关,但这似乎对任何功能都没有任何影响。您的里程可能会有所不同。

  3. Python-GNUPG版本和gpg二进制版本之间可能存在兼容性问题。这可能导致Unknown status message: [SOME-GPG-MESSAGE]错误;例如:Unknown status message: PINENTRY_LAUNCHED,我相信它会在gpg尝试显示密码提示时出现(在较早的版本中不会!)。如果您不打算在不同的OS上(我们曾经使用过)制作具有不同用途的模块,则可以在pip install打包后手动编辑python-gnupg源代码来尝试自己的运气。具体来说,在pretty_bad_protocol._parsers.py方法的_handle_status中,有一个已知状态消息的元组;只需在此处添加任何“未知”状态消息,该错误将来就不会出现。我的意思是,那之后您自己一个人,但这是我们尝试过的事情,似乎并没有伤害任何事情。

对于将来尝试进行pgp加密的人来说,这是最幸运的事情。

答案 1 :(得分:0)

感谢您提供所有详细信息。 我已经通过

解决了这个问题
gpg = gnupg.GPG(binary='/usr/bin/gpg2', homedir='/tmp')