Package duplicity :: Module GnuPGInterface
[hide private]
[frames] | no frames]

Module GnuPGInterface

source code

Interface to GNU Privacy Guard (GnuPG)

GnuPGInterface is a Python module to interface with GnuPG. It concentrates on interacting with GnuPG via filehandles, providing access to control GnuPG via versatile and extensible means.

This module is based on GnuPG::Interface, a Perl module by the same author.

Normally, using this module will involve creating a GnuPG object, setting some options in it's 'options' data member (which is of type Options), creating some pipes to talk with GnuPG, and then calling the run() method, which will connect those pipes to the GnuPG process. run() returns a Process object, which contains the filehandles to talk to GnuPG with.

Example code:

>>> import GnuPGInterface
>>>
>>> plaintext  = "Three blind mice"
>>> passphrase = "This is the passphrase"
>>>
>>> gnupg = GnuPGInterface.GnuPG()
>>> gnupg.options.armor = 1
>>> gnupg.options.meta_interactive = 0
>>> gnupg.options.extra_args.append('--no-secmem-warning')
>>>
>>> # Normally we might specify something in
>>> # gnupg.options.recipients, like
>>> # gnupg.options.recipients = [ '0xABCD1234', 'bob@foo.bar' ]
>>> # but since we're doing symmetric-only encryption, it's not needed.
>>> # If you are doing standard, public-key encryption, using
>>> # --encrypt, you will need to specify recipients before
>>> # calling gnupg.run()
>>>
>>> # First we'll encrypt the test_text input symmetrically
>>> p1 = gnupg.run(['--symmetric'],
...                create_fhs=['stdin', 'stdout', 'passphrase'])
>>>
>>> p1.handles['passphrase'].write(passphrase)
>>> p1.handles['passphrase'].close()
>>>
>>> p1.handles['stdin'].write(plaintext)
>>> p1.handles['stdin'].close()
>>>
>>> ciphertext = p1.handles['stdout'].read()
>>> p1.handles['stdout'].close()
>>>
>>> # process cleanup
>>> p1.wait()
>>>
>>> # Now we'll decrypt what we just encrypted it,
>>> # using the convience method to get the
>>> # passphrase to GnuPG
>>> gnupg.passphrase = passphrase
>>>
>>> p2 = gnupg.run(['--decrypt'], create_fhs=['stdin', 'stdout'])
>>>
>>> p2.handles['stdin'].write(ciphertext)
>>> p2.handles['stdin'].close()
>>>
>>> decrypted_plaintext = p2.handles['stdout'].read()
>>> p2.handles['stdout'].close()
>>>
>>> # process cleanup
>>> p2.wait()
>>>
>>> # Our decrypted plaintext:
>>> decrypted_plaintext
'Three blind mice'
>>>
>>> # ...and see it's the same as what we orignally encrypted
>>> assert decrypted_plaintext == plaintext,           "GnuPG decrypted output does not match original input"
>>>
>>>
>>> ##################################################
>>> # Now let's trying using run()'s attach_fhs paramter
>>>
>>> # we're assuming we're running on a unix...
>>> input = open('/etc/motd')
>>>
>>> p1 = gnupg.run(['--symmetric'], create_fhs=['stdout'],
...                                 attach_fhs={'stdin': input})
>>>
>>> # GnuPG will read the stdin from /etc/motd
>>> ciphertext = p1.handles['stdout'].read()
>>>
>>> # process cleanup
>>> p1.wait()
>>>
>>> # Now let's run the output through GnuPG
>>> # We'll write the output to a temporary file,
>>> import tempfile
>>> temp = tempfile.TemporaryFile()
>>>
>>> p2 = gnupg.run(['--decrypt'], create_fhs=['stdin'],
...                               attach_fhs={'stdout': temp})
>>>
>>> # give GnuPG our encrypted stuff from the first run
>>> p2.handles['stdin'].write(ciphertext)
>>> p2.handles['stdin'].close()
>>>
>>> # process cleanup
>>> p2.wait()
>>>
>>> # rewind the tempfile and see what GnuPG gave us
>>> temp.seek(0)
>>> decrypted_plaintext = temp.read()
>>>
>>> # compare what GnuPG decrypted with our original input
>>> input.seek(0)
>>> input_data = input.read()
>>>
>>> assert decrypted_plaintext == input_data,            "GnuPG decrypted output does not match original input"

To do things like public-key encryption, simply pass do something like:

gnupg.passphrase = 'My passphrase' gnupg.options.recipients = [ 'bob@foobar.com' ] gnupg.run( ['--sign', '--encrypt'], create_fhs=..., attach_fhs=...)

Here is an example of subclassing GnuPGInterface.GnuPG, so that it has an encrypt_string() method that returns ciphertext.

>>> import GnuPGInterface
>>>
>>> class MyGnuPG(GnuPGInterface.GnuPG):
...
...     def __init__(self):
...         GnuPGInterface.GnuPG.__init__(self)
...         self.setup_my_options()
...
...     def setup_my_options(self):
...         self.options.armor = 1
...         self.options.meta_interactive = 0
...         self.options.extra_args.append('--no-secmem-warning')
...
...     def encrypt_string(self, string, recipients):
...        gnupg.options.recipients = recipients   # a list!
...
...        proc = gnupg.run(['--encrypt'], create_fhs=['stdin', 'stdout'])
...
...        proc.handles['stdin'].write(string)
...        proc.handles['stdin'].close()
...
...        output = proc.handles['stdout'].read()
...        proc.handles['stdout'].close()
...
...        proc.wait()
...        return output
...
>>> gnupg = MyGnuPG()
>>> ciphertext = gnupg.encrypt_string("The secret", ['0x260C4FA3'])
>>>
>>> # just a small sanity test here for doctest
>>> import types
>>> assert isinstance(ciphertext, types.StringType),            "What GnuPG gave back is not a string!"

Here is an example of generating a key: >>> import GnuPGInterface >>> gnupg = GnuPGInterface.GnuPG() >>> gnupg.options.meta_interactive = 0 >>> >>> # We will be creative and use the logger filehandle to capture >>> # what GnuPG says this time, instead stderr; no stdout to listen to, >>> # but we capture logger to surpress the dry-run command. >>> # We also have to capture stdout since otherwise doctest complains; >>> # Normally you can let stdout through when generating a key. >>> >>> proc = gnupg.run(['--gen-key'], create_fhs=['stdin', 'stdout', ... 'logger']) >>> >>> proc.handles['stdin'].write('''Key-Type: DSA ... Key-Length: 1024 ... # We are only testing syntax this time, so dry-run ... %dry-run ... Subkey-Type: ELG-E ... Subkey-Length: 1024 ... Name-Real: Joe Tester ... Name-Comment: with stupid passphrase ... Name-Email: joe@foo.bar ... Expire-Date: 2y ... Passphrase: abc ... %pubring foo.pub ... %secring foo.sec ... ''') >>> >>> proc.handles['stdin'].close() >>> >>> report = proc.handles['logger'].read() >>> proc.handles['logger'].close() >>> >>> proc.wait()

COPYRIGHT:

Copyright (C) 2001 Frank J. Tobin, ftobin@neverending.org

LICENSE:

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/copyleft/lesser.html


Version: 0.3.2

Author: Frank J. Tobin, ftobin@neverending.org

Classes [hide private]
  GnuPG
Class instances represent GnuPG.
  Pipe
simple struct holding stuff about pipes we use
  Options
Objects of this class encompass options passed to GnuPG.
  Process
Objects of this class encompass properties of a GnuPG process spawned by GnuPG.run().
  GnuPGInterface
Class instances represent GnuPG.
Functions [hide private]
 
threaded_waitpid(process)
When started as a thread with the Process object, thread will execute an immediate waitpid() against the process pid and will collect the process termination info.
source code
 
_run_doctests() source code
Variables [hide private]
  __revision__ = '$Id: GnuPGInterface.py,v 1.6 2009/06/06 17:35:...
  _stds = ['stdin', 'stdout', 'stderr']
  _fd_modes = {'command': 'w', 'logger': 'r', 'passphrase': 'w',...
  _fd_options = {'command': '--command-fd', 'logger': '--logger-...
  __package__ = 'duplicity'
Function Details [hide private]

threaded_waitpid(process)

source code 

When started as a thread with the Process object, thread will execute an immediate waitpid() against the process pid and will collect the process termination info. This will allow us to reap child processes as soon as possible, thus freeing resources quickly.


Variables Details [hide private]

__revision__

Value:
'$Id: duplicity.GnuPGInterface-module.html,v 1.14 2011/11/25 19:41:03 loafman Exp $'

_fd_modes

Value:
{'command': 'w',
 'logger': 'r',
 'passphrase': 'w',
 'status': 'r',
 'stderr': 'r',
 'stdin': 'w',
 'stdout': 'r'}

_fd_options

Value:
{'command': '--command-fd',
 'logger': '--logger-fd',
 'passphrase': '--passphrase-fd',
 'status': '--status-fd'}