Fixed password length bug

Change from enum to fixed value
This commit is contained in:
Alexandre Possebom 2014-09-26 16:10:44 -03:00
parent c8b28c7ebd
commit 93c84f7584
1 changed files with 79 additions and 65 deletions

View File

@ -29,80 +29,87 @@ from util import Util
import hmac
import getpass
import argparse
def enum(**enums):
return type('Enum', (), enums)
def injectcharacter(mhash, offset, reserved, seed, length, cstart, cnum):
pos0 = seed % length
pos = (pos0 + offset) % length
for i in range(0, length - reserved):
tmp = (pos0 + reserved + i) % length
char = ord(mhash[tmp])
if char >= ord(cstart) and char < ord(cstart) + cnum:
return mhash
head = mhash[:pos] if pos > 0 else ""
inject = ((seed + ord(mhash[pos])) % cnum) + ord(cstart)
tail = mhash[pos+1:] if (pos + 1 < len(mhash)) else mhash
return head + chr(inject) + tail
import sys
def removespecialcharacters(mhash, seed, length):
inputchars = list(mhash)
pivot = 0
for i in range(0, length):
if not inputchars[i].isdigit() and not inputchars[i].isalpha():
inputchars[i] = chr(((seed + pivot) % 26 + ord('A')))
pivot = i + 1
return "".join(inputchars)
def converttodigits(mhash, seed, length):
inputchars = list(mhash)
pivot = 0
for i in range(0, length):
if not inputchars[i].isdigit():
inputchars[i] = chr(((seed + ord(inputchars[pivot])) % 10 +
ord('0')))
pivot = i + 1
return "".join(inputchars)
def generatehash(tag, key, length, password_type):
digest = hmac.new(key, tag, sha1).digest()
mhash = digest.encode('base64')[:-2]
seed = 0
for i in range(0, len(mhash)):
seed += ord(mhash[i])
if password_type == PASSWORDTYPE.NUMERIC:
mhash = converttodigits(mhash, seed, length)
else:
mhash = injectcharacter(mhash, 0, 4, seed, length, '0', 10)
if password_type == PASSWORDTYPE.ALPHANUMERIC_AND_SPECIAL_CHARS:
mhash = injectcharacter(mhash, 1, 4, seed, length, '!', 15)
mhash = injectcharacter(mhash, 2, 4, seed, length, 'A', 26)
mhash = injectcharacter(mhash, 3, 4, seed, length, 'a', 26)
if password_type == PASSWORDTYPE.ALPHANUMERIC:
mhash = removespecialcharacters(mhash, seed, length)
return mhash[:length]
class Twik(object):
def injectcharacter(self, mhash, offset, reserved, seed, length, cstart, cnum):
pos0 = seed % length
pos = (pos0 + offset) % length
for i in range(0, length - reserved):
tmp = (pos0 + reserved + i) % length
char = ord(mhash[tmp])
if char >= ord(cstart) and char < ord(cstart) + cnum:
return mhash
head = mhash[:pos] if pos > 0 else ""
inject = ((seed + ord(mhash[pos])) % cnum) + ord(cstart)
tail = mhash[pos+1:] if (pos + 1 < len(mhash)) else mhash
return head + chr(inject) + tail
def getpassword(tag, private_key, master_key, length, password_type):
mhash = generatehash(private_key, tag, 24, 1)
password = generatehash(mhash, master_key, length, password_type)
print "Your password is %s" % password
def removespecialcharacters(self, mhash, seed, length):
inputchars = list(mhash)
pivot = 0
for i in range(0, length):
if not inputchars[i].isdigit() and not inputchars[i].isalpha():
inputchars[i] = chr(((seed + pivot) % 26 + ord('A')))
pivot = i + 1
return "".join(inputchars)
def converttodigits(self, mhash, seed, length):
inputchars = list(mhash)
pivot = 0
for i in range(0, length):
if not inputchars[i].isdigit():
inputchars[i] = chr(((seed + ord(inputchars[pivot])) % 10 +
ord('0')))
pivot = i + 1
return "".join(inputchars)
def generatehash(self, tag, key, length, password_type):
digest = hmac.new(key, tag, sha1).digest()
mhash = digest.encode('base64')[:-2]
seed = 0
for i in range(0, len(mhash)):
seed += ord(mhash[i])
"""NUMERIC"""
if password_type == 3:
mhash = self.converttodigits(mhash, seed, length)
else:
mhash = self.injectcharacter(mhash, 0, 4, seed, length, '0', 10)
"""ALPHANUMERIC_AND_SPECIAL_CHARS"""
if password_type == 1:
mhash = self.injectcharacter(mhash, 1, 4, seed, length, '!', 15)
mhash = self.injectcharacter(mhash, 2, 4, seed, length, 'A', 26)
mhash = self.injectcharacter(mhash, 3, 4, seed, length, 'a', 26)
"""ALPHANUMERIC"""
if password_type == 2:
mhash = self.removespecialcharacters(mhash, seed, length)
return mhash[:length]
def getpassword(self, tag, private_key, master_key, length, password_type):
if length > 26 or length < 4:
return None
mhash = self.generatehash(private_key, tag, 24, 1)
password = self.generatehash(mhash, master_key, length, password_type)
return password
def main():
global PASSWORDTYPE
PASSWORDTYPE = enum(ALPHANUMERIC_AND_SPECIAL_CHARS=1, ALPHANUMERIC=2,
NUMERIC=3)
"""
ALPHANUMERIC_AND_SPECIAL_CHARS=1
ALPHANUMERIC=2
NUMERIC=3
"""
parser = argparse.ArgumentParser()
parser.add_argument("tag", type=str,
help="generate password for a specified tag")
parser.add_argument("-c", "--chars", type=int, default=-1,
help="length of generated password. Default: 12")
help="length of generated password [4-26]. Default: 12")
parser.add_argument("-p", "--profile", type=str, default='Profile',
help="profile to use. Default:'Profile'")
parser.add_argument("-t", "--passwordtype", type=int, choices=[1, 2, 3],
@ -115,13 +122,20 @@ def main():
''')
args = parser.parse_args()
if args.chars > 26 or args.chars < 4:
print "Invalid password length [4-26]"
sys.exit(2)
util = Util(args.tag, args.chars, args.passwordtype, args.profile)
master_key = getpass.getpass(prompt='Master Key: ')
getpassword(args.tag, util.get_privatekey(), master_key,
twik = Twik()
password = twik.getpassword(args.tag, util.get_privatekey(), master_key,
util.get_chars(), util.get_passord_type())
print "Your password is %s" % password
if __name__ == "__main__":
main()