Skip to content

Instantly share code, notes, and snippets.

@d33tah
Last active August 29, 2015 13:56
Show Gist options
  • Save d33tah/9177395 to your computer and use it in GitHub Desktop.
Save d33tah/9177395 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import urllib
import base64
import subprocess
import os
import fcntl
import sys
KEYSERVER_URL = "http://pgp.mit.edu/pks/lookup?op=get&search=0x%s"
def get_key(keyid):
filename = os.sep.join(["keys", keyid])
try:
f = open(filename)
ret = f.read()
f.close()
except:
# Download the key from the key server and extract it from the
# response.
raw_html = urllib.urlopen(KEYSERVER_URL % keyid).read()
key_start_pos = raw_html.find('\n\n') + 2
key_end_pos = raw_html.find('\n-----END PGP PUBLIC KEY BLOCK-----')
key = raw_html[key_start_pos:key_end_pos]
ret = base64.b64decode(key)
f = open(filename, "w")
f.write(ret)
f.close()
return ret
def parse_key(decoded):
# The --batch mode will prevent GnuPG from asking us for a password in case
# it recognizes the key as encrypted data or something.
s = subprocess.Popen(["/usr/bin/gpg", "--list-packets", "--batch"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
# The key servers are full of keys corrupt in many strange ways - it might
# happen that GnuPG will report us some problem and won't read from stdin
# any more. To solve the problem, I decided to switch it to non-blocking
# mode.
fd = s.stdin.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
try:
s.stdin.write(decoded)
except IOError:
s.terminate()
return {'uid': '', 'sigs': []}
s.stdin.flush()
s.stdin.close()
out = s.stdout.read()
s.stdout.close()
s.poll()
sigs = []
mode = ""
uid = "?"
for line in out.split('\n'):
if line.startswith(':user ID packet: '):
uid_raw = line.split(':user ID packet: ')[1]
uid_without_quotes = uid_raw[1:-1]
uid = uid_without_quotes.decode('string-escape')
elif line.startswith(':signature packet: '):
sig = line.split('keyid ')[1]
sigs += [sig]
# Return the UID and unique signatures.
sigs = list(set(sigs))
return {'uid': uid, 'sigs': sigs}
def traverse_DFS(start):
todo = [[start, [start]]]
visited = {}
while 0 < len(todo):
(node, path) = todo.pop(0)
if node in visited:
continue
else:
visited[node] = True
nodes = parse_key(get_key(node))
print("n=%d, uid=%s [%s]" % (len(todo), nodes['uid'], node))
for next_node in nodes['sigs']:
if next_node in path:
continue
else:
todo.append([next_node, path + [next_node]])
if __name__ == "__main__":
traverse_DFS('7909761da0a42745')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment