Skip to content

Instantly share code, notes, and snippets.

@craSH
Created May 24, 2011 20:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save craSH/989567 to your computer and use it in GitHub Desktop.
Save craSH/989567 to your computer and use it in GitHub Desktop.
Determine password for a PGP private key based on a wordlist.
#!/usr/bin/env python
"""
Determine password for a PGP private key based on a wordlist.
Also performs permutations on passwords in the case of l33tsp3ak, etc.
Requires python-gnupg (easy_install/pip install python-gnupg)
To quiet down some of the exceptions during signing attempts, the following
"patch" is needed within gnupg.py:
--- gnupg.py 2011-05-24 13:11:23.000000000 -0400
+++ gnupg_patched.py 2011-05-24 16:02:52.000000000 -0400
@@ -974,6 +974,8 @@
if key in ("USERID_HINT", "NEED_PASSPHRASE", "BAD_PASSPHRASE",
"GOOD_PASSPHRASE", "BEGIN_SIGNING"):
pass
+ elif key == "INV_SGNR":
+ pass
elif key == "SIG_CREATED":
(self.type,
algo, hashalgo, cls,
Example Usage:
gpg_bruteforce.py <key_id> [-p] < /usr/share/dict/words
Copyleft 2011 Ian Gallagher <crash@neg9.org>
Inspired by idea/work of Aaron Grattifiori <dyn@neg9.org>
"""
import sys
import os
from datetime import datetime
from gnupg import GPG
def verifyPassphrase(signing_key, key_passphrase):
"""
Return True if passphrase is correct, False if it is not
"""
# Setup GPG
gnupg_home = "%s/.gnupg" % os.environ['HOME']
gpg = GPG(gnupghome=gnupg_home)
sig = None
try:
# This bugger is threaded, so catching exceptions from it isn't really something that works so great
sig = gpg.sign('Test String', keyid=signing_key, passphrase=key_passphrase, clearsign=False)
except Exception:
pass
if sig:
return True
else:
return False
if "__main__" == __name__:
if len(sys.argv) < 2:
print >>sys.stderr, "usage: %s <key_id> [-p] < <wordlist>" % sys.argv[0]
print >>sys.stderr, "\t<key_id>: PGP KeyID/Fingerprint to test."
print >>sys.stderr, "\t-p: Attempt variations of each word in the wordlist."
print >>sys.stderr, "\t<wordlist>: A file containing passwords to attempt, one per line."
sys.exit(1)
keyid = sys.argv[1]
try_permutations = True if (len(sys.argv) > 2 and sys.argv[2].lower() == '-p') else False
attempts = 0
valid_password = None
passwords = sys.stdin.readlines()
time_start = datetime.now()
for password in passwords:
attempts += 1
if verifyPassphrase(keyid, password):
valid_password = password
break
if try_permutations:
"""
Need to write some code that will take a word, and make a generator of all/many
variations of it based on latin "rules" of some sort.
E.g/: catfish -> c4tfish, ca7fish, catf!sh, c4tf!5h, Catfish, caTfish, ...
"""
# TODO: Implement below
"""
for permutation in permutate(password):
attempts += 1
if verifyPassphrase(keyid, permutation):
valid_password = password
break
"""
time_end = datetime.now()
if valid_password:
print "Success! Passphrase for keyid %s: %s" % (keyid, valid_password[:-1] if valid_password[-1] == "\n" else valid_password)
print >>sys.stderr, "Number of attempts until success: %d" % attempts
else:
print "Sorry, no password found after %d attempts :(" % attempts
print >>sys.stderr, "Total run time: %s" % (time_end - time_start)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment