Fixed password length bug
Change from enum to fixed value
This commit is contained in:
parent
c8b28c7ebd
commit
93c84f7584
144
twik/twik.py
144
twik/twik.py
|
@ -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()
|
||||
|
||||
|
|
Loading…
Reference in New Issue