Remove temporary files after signing.
[0publish.git] / signing.py
blob65a2832a3f80985ee582d7b035a609fcdaca9ef4
1 from zeroinstall.injector import gpg
2 import tempfile, os, base64
4 def check_signature(path):
5 data = file(path).read()
6 xml_comment = data.rfind('\n<!-- Base64 Signature')
7 if xml_comment >= 0:
8 data_stream, sigs = gpg.check_stream(file(path))
9 sign_fn = sign_xml
10 data = data[:xml_comment + 1]
11 data_stream.close()
12 elif data.startswith('BEGIN'):
13 data_stream, sigs = gpg.check_stream(file(path))
14 sign_fn = sign_plain
15 data = data_stream.read()
16 else:
17 return data, sign_unsigned, None
18 for sig in sigs:
19 if isinstance(sig, gpg.ValidSig):
20 return data, sign_fn, sig.fingerprint
21 raise Exception('No valid signatures found!')
23 def write_tmp(path, data):
24 """Create a temporary file in the same directory as 'path' and write data to it."""
25 fd, tmp = tempfile.mkstemp(prefix = 'tmp-', dir = os.path.dirname(path))
26 stream = os.fdopen(fd, 'w')
27 stream.write(data)
28 stream.close()
29 return tmp
31 def run_gpg(default_key, *arguments):
32 arguments = list(arguments)
33 if default_key is not None:
34 arguments = ['--default-key', default_key] + arguments
35 arguments.insert(0, 'gpg')
36 if os.spawnvp(os.P_WAIT, 'gpg', arguments):
37 raise Exception("Command '%s' failed" % arguments)
39 def sign_unsigned(path, data, key):
40 os.rename(write_tmp(path, data), path)
42 def sign_plain(path, data, key):
43 tmp = write_tmp(path, data)
44 try:
45 run_gpg(key, '--clearsign', tmp)
46 except:
47 os.unlink(tmp)
48 raise
49 os.rename(tmp + '.asc', path)
51 def sign_xml(path, data, key):
52 tmp = write_tmp(path, data)
53 try:
54 run_gpg(key, '--detach-sign', tmp)
55 finally:
56 os.unlink(tmp)
57 tmp += '.sig'
58 encoded = base64.encodestring(file(tmp).read())
59 os.unlink(tmp)
60 sig = "<!-- Base64 Signature\n" + encoded + "\n-->\n"
61 os.rename(write_tmp(path, data + sig), path)