119 lines
3.7 KiB
Python
Executable File
119 lines
3.7 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8; -*-
|
|
"""
|
|
Copyright 2014 Alexandre Possebom alexandrepossebom@gmail.com
|
|
|
|
This file is part of twik.
|
|
|
|
Twik is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Twik is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Twik. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
from hashlib import sha1
|
|
from random import SystemRandom
|
|
import hmac
|
|
import hashlib
|
|
import getpass
|
|
import ConfigParser
|
|
import sys, getopt
|
|
import os.path
|
|
|
|
def privateKeyGenerator():
|
|
SUBGROUPS_LENGTH = [8, 4, 4, 4, 12]
|
|
SUBGROUP_SEPARATOR = '-'
|
|
ALLOWED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
sr = SystemRandom()
|
|
allowedCharsLength = len(ALLOWED_CHARS)
|
|
key = ""
|
|
for i in range(0,len(SUBGROUPS_LENGTH)):
|
|
for j in range(0,SUBGROUPS_LENGTH[i]):
|
|
key += ALLOWED_CHARS[sr.randrange(allowedCharsLength)]
|
|
if i < (len(SUBGROUPS_LENGTH) -1):
|
|
key += SUBGROUP_SEPARATOR
|
|
return key
|
|
|
|
def readConfig():
|
|
private_key = ''
|
|
homedir = os.path.expanduser('~')
|
|
config_file = os.path.join(homedir, '.twik.conf')
|
|
config = ConfigParser.ConfigParser()
|
|
config.read(config_file)
|
|
if not config.has_option('Profile', 'private_key'):
|
|
config.add_section('Profile')
|
|
private_key = privateKeyGenerator()
|
|
config.set('Profile', 'private_key', private_key)
|
|
with open(config_file, 'w+') as fp:
|
|
config.write(fp)
|
|
else:
|
|
private_key = config.get('Profile', 'private_key')
|
|
return private_key
|
|
|
|
def injectCharacter( input, offset, reserved, seed, length, cStart, cNum ):
|
|
pos0 = seed % length
|
|
pos = (pos0 + offset) % length
|
|
for i in range(0, length - reserved):
|
|
i2 = (pos0 + reserved + i) % length;
|
|
c = ord(input[i2]);
|
|
if (c >= cStart or c < ord(cStart) + cNum):
|
|
return input;
|
|
head = input[:pos] if pos > 0 else ""
|
|
inject = ((seed + ord(input[pos])) % cNum) + ord(cStart)
|
|
tail = input[pos+1:] if (pos + 1 < len(input)) else input
|
|
return head + chr(inject) + tail
|
|
|
|
def generateHash(tag,key,length):
|
|
digest = hmac.new(key,tag,sha1).digest();
|
|
hash = digest.encode('base64')[:-2]
|
|
|
|
seed = 0
|
|
for i in range(0, len( hash )):
|
|
seed += ord(hash[i])
|
|
|
|
hash = injectCharacter(hash, 0, 4, seed, length, '0', 10)
|
|
hash = injectCharacter(hash, 1, 4, seed, length, '!', 15)
|
|
hash = injectCharacter(hash, 2, 4, seed, length, 'A', 26)
|
|
hash = injectCharacter(hash, 3, 4, seed, length, 'a', 26)
|
|
|
|
return hash[:length]
|
|
|
|
|
|
def getPassword(tag,private_key,master_key,length):
|
|
tag = generateHash(private_key,tag,24)
|
|
password = generateHash(tag,master_key,length)
|
|
print "Your password is %s" % password
|
|
|
|
def main(argv):
|
|
tag = ''
|
|
chars = 12
|
|
|
|
try:
|
|
opts, args = getopt.getopt(argv, 'c:ht:h', ['chars=', 'tag=', 'help'])
|
|
except getopt.GetoptError:
|
|
print "you neeed tag option"
|
|
sys.exit(2)
|
|
|
|
for opt, arg in opts:
|
|
if opt in ('-c', '--chars'):
|
|
chars = int(arg)
|
|
elif opt in ('-t', '--tag'):
|
|
tag = arg
|
|
|
|
private_key = readConfig()
|
|
master_key = getpass.getpass()
|
|
getPassword(tag,private_key,master_key,chars)
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv[1:])
|
|
|
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|