0
votes

I’m trying to get Python pexpect to work with GNU gpg. We do not have the gnupg module loaded and trying to do so would be nearly impossible.

I can get pexepct to work doing FTP and SSH, but with gpg I’m having a slight problem. Below is the command I run to decrypt the file from the command line. I enter the passphrase at the prompt and it works perfectly.

# gpg --decrypt encKey_20141009_b7489540_36.00.tar.gpg > encKey_20141009_b7489540_36.00.tar

You need a passphrase to unlock the secret key for user: "XXXXXXXXXXXXXXXXXXXXXXXXXXX" 2048-bit RSA key, ID AD22F55F, created 2013-07-18 (main key ID 0D56620B)

Enter passphrase:

Yet when I try to use pexpect I have a problem. Below is the code that I’m trying to get to work:

#!/usr/bin/python

import pexpect
Password = raw_input('Enter passphrase:  ')

child = pexpect.spawn('gpg --decrypt encKey_20141009.tar.gpg > encKey_20141009_.tar')
child.expect('Enter passphrase: ')
child.sendline(Password)

Below is the error that I receive:

Traceback (most recent call last):
  File "./pexepect.py", line 9, in ?
child.expect('Enter passphrase: ')
 File "/usr/lib/python2.4/site-packages/pexpect.py", line 1311, in expect
return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
File "/usr/lib/python2.4/site-packages/pexpect.py", line 1325, in expect_list
  return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
File "/usr/lib/python2.4/site-packages/pexpect.py", line 1396, in expect_loop
raise EOF (str(e) + '\n' + str(self))
pexpect.EOF: End Of File (EOF) in read_nonblocking(). Exception style platform.
<pexpect.spawn object at 0x2b2dfe13f350>
version: 2.3 ($Revision: 399 $)
command: /usr/bin/gpg
args: ['/usr/bin/gpg', '--decrypt', 'encKey_20141009.tar.gpg', '>', 'encKey_20141009.tar']
searcher: searcher_re:
    0: re.compile("Enter passphrase: ")
buffer (last 100 chars):
before (last 100 chars): usage: gpg [options] --decrypt [filename]

after: pexpect.EOF
match: None
match_index: None
exitstatus: 2
flag_eof: True
pid: 14399
child_fd: 3
closed: False
timeout: 30
delimiter: pexpect.EOF
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
1

1 Answers

0
votes

> is a redirection in shell. pexpect doesn't run shell, it runs gpg executable. Specify the output file using gpg options instead (--output).

Here's how to run gpg using subprocess module:

#!/usr/bin/env python3
import os
from subprocess import Popen

passphrase = input('Enter passphrase: ')
file_to_decrypt = 'encKey_20141009.tar.gpg'
in_fd, out_fd = os.pipe()
cmd = ['gpg', '--passphrase-fd', str(in_fd)]
cmd += ['--output', os.path.splitext(file_to_decrypt)[0]]
cmd += ['--decrypt', file_to_decrypt]
with Popen(cmd, pass_fds=[in_fd]):
    os.close(in_fd) # unused in the parent
    with open(out_fd, 'w') as out_file:
        out_file.write(passphrase)