-
-
Save tzarskyz/6474745 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Will either compute a passwordmaker style key from `sha256(mp + site + | |
username)` or open a symmetrically keyed gpg file and lookup a specific | |
site-key for the username and password. The keyfile must follow the following | |
format:: | |
foobar.com: | |
username: johnuser | |
password: megaleet | |
""" | |
from argparse import ArgumentParser | |
import getpass | |
import hashlib | |
import math | |
import gnupg | |
import yaml | |
CHARSET = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
"abcdefghijklmnopqrstuvwxyz" | |
"0123456789`~!@#$%^&*()_-+={}|[]\\:\";\'<>?,./") | |
# `copy_url` from lodgeit.py | |
# :license: 3-Clause BSD | |
# :authors: 2007-2008 Georg Brandl <[email protected]>, | |
# 2006 Armin Ronacher <[email protected]>, | |
# 2006 Matt Good <[email protected]>, | |
# 2005 Raphael Slinckx <[email protected]> | |
def clipboard_copy(item): | |
"""Copy the item into the clipboard.""" | |
# try windows first | |
try: | |
import win32clipboard | |
except ImportError: | |
# then give pbcopy a try. do that before gtk because | |
# gtk might be installed on os x but nobody is interested | |
# in the X11 clipboard there. | |
from subprocess import Popen, PIPE | |
for prog in 'pbcopy', 'xclip': | |
try: | |
client = Popen([prog], stdin=PIPE) | |
except OSError: | |
continue | |
else: | |
client.stdin.write(item) | |
client.stdin.close() | |
client.wait() | |
break | |
else: | |
try: | |
import pygtk | |
pygtk.require('2.0') | |
import gtk | |
import gobject | |
except ImportError: | |
return | |
gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD).set_text(item) | |
gobject.idle_add(gtk.main_quit) | |
gtk.main() | |
else: | |
win32clipboard.OpenClipboard() | |
win32clipboard.EmptyClipboard() | |
win32clipboard.SetClipboardText(item) | |
win32clipboard.CloseClipboard() | |
def rstr2any(input, encoding, trim=True): | |
"""Convert a raw string to an arbitrary string encoding. Set trim | |
to false for keeping leading zeros | |
""" | |
divisor = len(encoding) | |
remainders = [] | |
# Convert to an array of 16-bit big-endian values, forming the dividend | |
dividend = [] | |
# pad this | |
while len(dividend) < math.ceil(len(input) / 2): | |
dividend.append(0) | |
for i in range(len(dividend)): | |
dividend[i] = (ord(input[i * 2]) << 8) | ord(input[i * 2 + 1]) | |
# Repeatedly perform a long division. The binary array forms the dividend, | |
# the length of the encoding is the divisor. Once computed, the quotient | |
# forms the dividend for the next step. We stop when the dividend is zero. | |
# All remainders are stored for later use. | |
while len(dividend) > 0: | |
quotient = [] | |
x = 0 | |
for i in range(len(dividend)): | |
x = (int(x) << 16) + dividend[i] | |
q = math.floor(x / divisor) | |
x -= q * divisor | |
if len(quotient) > 0 or q > 0: | |
quotient.append(q) | |
remainders.append(x) | |
dividend = quotient | |
# Convert the remainders to the output string | |
output = "" | |
for i in range(len(remainders) - 1, 0, -1): | |
output += encoding[int(remainders[i])] | |
return output | |
def main(): | |
parser = ArgumentParser() | |
parser.add_argument('-f', '--file', | |
help='GPG file to use for looking up keys', | |
type=file) | |
parser.add_argument('-u', '--user', | |
help='Username default', | |
default=getpass.getuser()) | |
mutex_group = parser.add_mutually_exclusive_group() | |
mutex_group.add_argument('-l', '--list', action='store_true') | |
mutex_group.add_argument('-g', '--generate') | |
mutex_group.add_argument('-s', '--select') | |
namespace = parser.parse_args() | |
if namespace.list or namespace.select: | |
symmetric_phrase = getpass.getpass('passphrase: ') | |
gpg = gnupg.GPG() | |
crypt = gpg.decrypt_file(namespace.file, passphrase=symmetric_phrase) | |
key_data = yaml.load(crypt.data) | |
if namespace.list: | |
print key_data.keys() | |
return | |
elif namespace.select: | |
# TODO:dc: check for the key in key_data | |
username = key_data[namespace.select].get('username', '') | |
pass_ = key_data[namespace.select].get('password', '') | |
else: | |
mp = getpass.getpass('master key: ') | |
site = raw_input('site: ') | |
username = namespace.user | |
hash_ = hashlib.sha256(mp + site + username).digest() | |
pass_ = rstr2any(hash_, CHARSET)[:20] | |
clipboard_copy(pass_) | |
print username | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment