1
# Code for running GnuPG in batch mode and dealing with the results
3
__rcsid__ = '$Id: GPG.py,v 1.1.1.1 2000/04/17 02:17:24 amk Exp $'
6
import cStringIO, popen2
9
"Class used to hold information about a signature result"
13
self.fingerprint = self.creation_date = self.timestamp = None
14
self.signature_id = self.key_id = None
22
# Default path used for searching for the GPG binary, when the
23
# PATH environment variable isn't set.
24
DEFAULT_PATH = ['/bin', '/usr/bin', '/usr/local/bin']
26
def __init__(self, gpg_binary = None):
27
"""Initialize an object instance. Options are:
29
gpg_binary -- full pathname for GPG binary. If not supplied,
30
the current value of PATH will be searched, falling back to the
31
DEFAULT_PATH class variable if PATH isn't available.
34
# If needed, look for the gpg binary along the path
35
if gpg_binary is None:
37
if os.environ.has_key('PATH'):
38
path = os.environ['PATH']
39
path = string.split(path, os.pathsep)
41
path = self.DEFAULT_PATH
44
fullname = os.path.join(dir, 'gpg')
45
if os.path.exists( fullname ):
49
raise ValueError, ("Couldn't find 'gpg' binary on path"
52
self.gpg_binary = gpg_binary
54
def verify(self, data):
55
"Verify the signature on the contents of the string 'data'"
56
file = cStringIO.StringIO( data )
57
return self.verify_file( file )
59
def verify_file(self, file):
60
"Verify the signature on the contents of the file-like object 'file'"
61
child_stdout, child_stdin, child_stderr = self._open_subprocess()
63
# Copy the file to the GPG subprocess
65
data = file.read(1024)
67
child_stdin.write(data)
71
# Get the response information
72
resp = self._read_response(child_stderr)
74
# Create an object to return, and fill it with data
76
if resp.has_key('BADSIG'):
78
sig.key_id, sig.username = string.split(resp['BADSIG'], None, 1)
79
elif resp.has_key('GOODSIG'):
81
sig.key_id, sig.username = string.split(resp['GOODSIG'], None, 1)
83
if resp.has_key('VALIDSIG'):
84
L = string.split(resp['VALIDSIG'], None)
85
sig.fingerprint, sig.creation_date, sig.timestamp = L[0], L[1], L[2]
87
if resp.has_key('SIG_ID'):
88
L = string.split(resp['SIG_ID'], None)
89
sig.signature_id, sig.creation_date, sig.timestamp = L
91
# Read the contents of the file from GPG's stdout
94
data = child_stdout.read(1024)
96
sig.data = sig.data + data
100
def _open_subprocess(self, *args):
101
# Internal method: open a pipe to a GPG subprocess and return
102
# the file objects for communicating with it.
104
cmd = self.gpg_binary + ' --status-fd 2 ' + string.join(args)
106
child_stdout, child_stdin, child_stderr = popen2.popen3(cmd)
107
return child_stdout, child_stdin, child_stderr
109
def _read_response(self, child_stdout):
110
# Internal method: reads all the output from GPG, taking notice
111
# only of lines that begin with the magic [GNUPG:] prefix.
112
# (See doc/DETAILS in the GPG distribution for info on GPG's
113
# output when --status-fd is specified.)
115
# Returns a dictionary, mapping GPG's keywords to the arguments
120
line = child_stdout.readline()
122
line = string.rstrip( line )
123
if line[0:9] == '[GNUPG:] ':
124
# Chop off the prefix
126
L = string.split(line, None, 1)
129
resp[ keyword ] = L[1]
135
# Not yet implemented, because I don't need these methods
136
# The methods certainly don't have all the parameters they'd need.
138
def sign(self, data):
139
"Sign the contents of the string 'data'"
142
def sign_file(self, file):
143
"Sign the contents of the file-like object 'file'"
146
def encrypt_file(self, file):
147
"Encrypt the message read from the file-like object 'file'"
150
def encrypt(self, data):
151
"Encrypt the message contained in the string 'data'"
154
def decrypt_file(self, file):
155
"Decrypt the message read from the file-like object 'file'"
158
def decrypt(self, data):
159
"Decrypt the message contained in the string 'data'"
163
if __name__ == '__main__':
165
if len(sys.argv) == 1:
166
print 'Usage: GPG.py <signed file>'
169
obj = GPGSubprocess()
170
file = open(sys.argv[1], 'rb')
171
sig = obj.verify_file( file )