#!/usr/bin/env python2 """Fill in the first digits of the hash in a form created by gpgparticipants.""" __version__ = "1.0" __author__ = "Stefan Huber" __email__ = "shuber@sthu.org" __copyright__ = "Copyright 2013, Stefan Huber" __license__ = "MIT" # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. import sys import hashlib import getopt def insertspaces(s): """Inserts a space after every 4-th character, and three spaces after every 8-th character of string s.""" def inpacks(s, n): while len(s) > 0: yield s[0:n] s = s[n:] out = " ".join([ " ".join(inpacks(octp, 4)) for octp in inpacks(s, 8)]) return out def range_hex(length): """Give all hex-strings from 00...0 until ff...f of given length.""" if length == 0: yield "" elif length == 1: for c in "0123456789abcdef": yield c elif length > 1: for prefix in range_hex(length-1): for postfix in range_hex(1): yield prefix + postfix def usage(): """Print --help text""" print("""Usage: {0} {0} --help {0} -h Takes a file produced by gpgparticipants as and trys to fill in some digits into the SHA256 field such that the resulting list actually has a SHA256 checksum that starts with those digits. Whenever a match is found a file with the digits filled in is written to `.DIGITS`. OPTIONS: --fastforward If a match is found of given length and --fastforward is given then the program immediately jumps to the next length. --min-length NUM Start search with given length """.format(sys.argv[0])) if __name__ == "__main__": fastforward = False minlength = 1 optlist, args = getopt.getopt(sys.argv[1:], 'h', ['fastforward', 'min-length=']) for o, a in optlist: if o in ("-h", "--help"): usage() exit(0) if o in ("--fastforward"): fastforward = True if o in ("--min-length"): minlength = int(a) if len(args) < 2: print >>sys.stderr, "You need to give two filenames.""" exit(1) emptyfile = open(args[0]).read() idx = emptyfile.find("SHA256 Checksum:") idx = emptyfile.find("_", idx) for l in range(minlength, 32): print "Looking at length", l for h in range_hex(l): H = insertspaces(h.upper()) filledfile = emptyfile[:idx] + H + emptyfile[idx+len(H):] actual = hashlib.sha256(filledfile).hexdigest() if actual[:len(h)] == h: print "Found: ", H open(args[1] + "." + h, "w").write(filledfile) if fastforward: break