Encrypt file with GPG in python 3 with subprocess

六眼飞鱼酱① 提交于 2019-12-24 05:26:26

问题


How do I encrypt file with subprocess, so the output will be string.

 password = '%030x' % random.randrange(16**30)
 encrypted_file = subprocess.geststatusoutput("echo "+password+
 "|gpg --password-fd 0 < "+ name_of_selected_file)

I want to encrypted _file to be a string so I could use it as encrypted file to upload with post request.
What is the best way to do it with gnupg library?


回答1:


You can use subprocess.Popen() to execute a gpg command like this:

import shlex
import random
from subprocess import Popen, PIPE

passphrase = '%030x' % random.randrange(16**30)
source_filename = '/tmp/somefile'
cmd = 'gpg --batch --symmetric --cipher-algo AES256 --passphrase-fd 0 --output - {}'.format(source_filename)

# error handling omitted
p = Popen(shlex.split(cmd), stdout=PIPE, stdin=PIPE, stderr=PIPE)
encrypted_data = p.communicate(passphrase.encode())[0]

# Decryption - should work for Python 2 & 3
import os

r, w = os.pipe()    # pipe for sending passphrase from parent to child
try:
    os.set_inheritable(r, True)
except AttributeError:      # new in version 3.4
    pass
cmd = 'gpg --batch --decrypt --passphrase-fd {}'.format(r)
p = Popen(shlex.split(cmd), stdout=PIPE, stdin=PIPE, stderr=PIPE, close_fds=False)
os.close(r)    # closes fd in parent, child needs it
f = os.fdopen(w, 'w')
f.write(passphrase + '\n')    # '\n' seems required for Python 2 ???
f.close()
decrypted_data, stderr = p.communicate(encrypted_data)

# check that data was successfully roundtripped
assert open(source_filename).read() == decrypted_data.decode()

Or, decryption for Python 3 only:

import os
r, w = os.pipe()
cmd = 'gpg --batch --decrypt --passphrase-fd {}'.format(r)
p = Popen(shlex.split(cmd), stdout=PIPE, stdin=PIPE, stderr=PIPE, pass_fds=(r,))
os.close(r)    # closes fd in parent, child needs it
open(w, 'w').write(passphrase)
decrypted_data, stderr = p.communicate(encrypted_data)

# check that data was successfully roundtripped
assert open(source_filename).read() == decrypted_data.decode()

Now I am not an expert on the security of this method, however, writing the passphrase directly to the child process' stdin with communicate() is better than echoing the passphrase on the command line - which would be visible to anybody that could run ps or equivalent.

Also, relying on the shell level IO redirection of your command would require the shell=True argument to Popen which might have other security implications (see the warning in the Popen() documentation).

I have assumed in my gpg command that you are intending to use a symmetric encryption (your example does not suggest otherwise). If the remote server needs to be able to decrypt the encrypted file content, how are you going to share the generated passphrase?

You might be better off looking at using public key crypto instead.



来源:https://stackoverflow.com/questions/31501191/encrypt-file-with-gpg-in-python-3-with-subprocess

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!