Update to python 3
This commit is contained in:
parent
432c3359c1
commit
03a3edbd5b
|
@ -0,0 +1,125 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "pypy"
|
||||
install: python setup.py install
|
||||
script: nosetests
|
1
setup.py
1
setup.py
|
@ -16,3 +16,4 @@ setup(name='twik',
|
|||
'console_scripts': ['twik = twik.run:main'],
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@ class SimpleTest(unittest.TestCase):
|
|||
|
||||
def testPasswordAphanumericAndSpecialChars(self):
|
||||
for chars in range(4, 27):
|
||||
password = self.t.getpassword('tag',
|
||||
'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 1)
|
||||
password = self.t.getpassword('tag', 'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 1)
|
||||
if chars == 4:
|
||||
self.assertEqual(password, 'm3/I')
|
||||
if chars == 8:
|
||||
|
@ -23,8 +22,7 @@ class SimpleTest(unittest.TestCase):
|
|||
|
||||
def testPasswordAlphanumeric(self):
|
||||
for chars in range(4, 27):
|
||||
password = self.t.getpassword('tag',
|
||||
'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 2)
|
||||
password = self.t.getpassword('tag', 'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 2)
|
||||
if chars == 4:
|
||||
self.assertEqual(password, 'm31I')
|
||||
if chars == 8:
|
||||
|
@ -38,8 +36,7 @@ class SimpleTest(unittest.TestCase):
|
|||
|
||||
def testPasswordNumeric(self):
|
||||
for chars in range(4, 27):
|
||||
password = self.t.getpassword('tag',
|
||||
'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 3)
|
||||
password = self.t.getpassword('tag', 'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 3)
|
||||
if chars == 4:
|
||||
self.assertEqual(password, '4315')
|
||||
if chars == 8:
|
||||
|
@ -53,17 +50,14 @@ class SimpleTest(unittest.TestCase):
|
|||
|
||||
def testSize(self):
|
||||
for chars in range(4, 27):
|
||||
password = self.t.getpassword('tag',
|
||||
'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 1)
|
||||
password = self.t.getpassword('tag', 'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', chars, 1)
|
||||
self.assertEqual(len(password), chars)
|
||||
|
||||
def testSizeWrong(self):
|
||||
password = self.t.getpassword('tag',
|
||||
'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', 100, 1)
|
||||
password = self.t.getpassword('tag', 'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', 100, 1)
|
||||
self.assertEqual(password, None)
|
||||
def testSize(self):
|
||||
password = self.t.getpassword('tag',
|
||||
'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', 0, 1)
|
||||
password = self.t.getpassword('tag', 'TFCY2AJI-NBPU-V01E-F7CP-PJIZNRKPF25W', 'foobar', 0, 1)
|
||||
self.assertEqual(password, None)
|
||||
|
||||
def tearDown(self):
|
||||
|
|
14
twik/run.py
14
twik/run.py
|
@ -18,8 +18,8 @@ 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 util import Util
|
||||
from twik import Twik
|
||||
from .util import Util
|
||||
from .twik import Twik
|
||||
import getpass
|
||||
import argparse
|
||||
import sys
|
||||
|
@ -34,7 +34,7 @@ def main():
|
|||
parser.add_argument("tag", type=str,
|
||||
help="generate password for a specified tag")
|
||||
parser.add_argument("-c", "--chars", type=int,
|
||||
choices=range(4, 27),
|
||||
choices=list(range(4, 27)),
|
||||
metavar="[4-26]",
|
||||
help="length of generated password [4-26]. Default: 12")
|
||||
parser.add_argument("-p", "--profile", type=str, default=None,
|
||||
|
@ -53,16 +53,18 @@ def main():
|
|||
try:
|
||||
master_key = getpass.getpass(prompt='Master Key: ')
|
||||
except KeyboardInterrupt:
|
||||
print "^C"
|
||||
print("^C")
|
||||
raise SystemExit(0)
|
||||
|
||||
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
|
||||
print(password, end='')
|
||||
print('', file=sys.stderr)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
|
|
35
twik/twik.py
35
twik/twik.py
|
@ -24,12 +24,14 @@ 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 util import Util
|
||||
import hmac
|
||||
import getpass
|
||||
import argparse
|
||||
import base64
|
||||
import getpass
|
||||
import hmac
|
||||
import sys
|
||||
from hashlib import sha1
|
||||
|
||||
from .util import Util
|
||||
|
||||
|
||||
class Twik(object):
|
||||
|
@ -41,7 +43,7 @@ class Twik(object):
|
|||
char = ord(mhash[tmp])
|
||||
if char >= ord(cstart) and char < ord(cstart) + cnum:
|
||||
return mhash
|
||||
head = mhash[:pos] if pos > 0 else ""
|
||||
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
|
||||
|
@ -54,7 +56,7 @@ class Twik(object):
|
|||
if not inputchars[i].isdigit() and not inputchars[i].isalpha():
|
||||
inputchars[i] = chr(((seed + pivot) % 26 + ord('A')))
|
||||
pivot = i + 1
|
||||
return "".join(inputchars)
|
||||
return ''.join(inputchars)
|
||||
|
||||
def converttodigits(self, mhash, seed, length):
|
||||
inputchars = list(mhash)
|
||||
|
@ -64,28 +66,26 @@ class Twik(object):
|
|||
inputchars[i] = chr(((seed + ord(inputchars[pivot])) % 10 +
|
||||
ord('0')))
|
||||
pivot = i + 1
|
||||
return "".join(inputchars)
|
||||
return ''.join(inputchars)
|
||||
|
||||
def generatehash(self, tag, key, length, password_type):
|
||||
digest = hmac.new(key, tag, sha1).digest()
|
||||
mhash = digest.encode('base64')[:-2]
|
||||
digest = hmac.new(str.encode(key), str.encode(tag), sha1).digest()
|
||||
mhash = base64.b64encode(digest)[:-1]
|
||||
mhash = mhash.decode('utf-8')
|
||||
seed = sum([ord(i) for i in mhash])
|
||||
|
||||
seed = 0
|
||||
for i in range(0, len(mhash)):
|
||||
seed += ord(mhash[i])
|
||||
|
||||
"""NUMERIC"""
|
||||
# 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"""
|
||||
# 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"""
|
||||
# ALPHANUMERIC
|
||||
if password_type == 2:
|
||||
mhash = self.removespecialcharacters(mhash, seed, length)
|
||||
|
||||
|
@ -99,4 +99,5 @@ class Twik(object):
|
|||
password = self.generatehash(mhash, master_key, length, password_type)
|
||||
return password
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
|
|
24
twik/util.py
24
twik/util.py
|
@ -24,8 +24,9 @@ You should have received a copy of the GNU General Public License
|
|||
along with Twik. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import configparser
|
||||
import os.path
|
||||
import ConfigParser
|
||||
import sys
|
||||
from random import SystemRandom
|
||||
|
||||
def privatekeygenerator():
|
||||
|
@ -55,7 +56,7 @@ class Util(object):
|
|||
"""
|
||||
homedir = os.path.expanduser('~')
|
||||
self.filename = os.path.join(homedir, '.twik.conf')
|
||||
self.config = ConfigParser.ConfigParser()
|
||||
self.config = configparser.ConfigParser()
|
||||
self.config.read(self.filename)
|
||||
self.tag = tag
|
||||
self.chars = chars
|
||||
|
@ -83,7 +84,7 @@ class Util(object):
|
|||
break
|
||||
if self.profile == None:
|
||||
self.profile = self.config.sections()[0]
|
||||
print 'Using profile : %s' % self.profile
|
||||
print(f'Using profile: {self.profile}', file=sys.stderr)
|
||||
|
||||
if self.profile and self.config.has_option(self.profile, 'private_key'):
|
||||
private_key = self.config.get(self.profile, 'private_key')
|
||||
|
@ -104,29 +105,29 @@ class Util(object):
|
|||
if self.profile == 'Personal':
|
||||
self.config.set(self.profile, 'default', 1)
|
||||
self.writeconfig()
|
||||
print 'New profile is generated'
|
||||
print('New profile is generated')
|
||||
self.config.read(self.filename)
|
||||
return private_key
|
||||
|
||||
def get_chars(self):
|
||||
config_key = '%s_chars' % self.tag
|
||||
config_key = f'{self.tag}_chars'
|
||||
|
||||
if self.config.has_option(self.profile, config_key) and self.chars == None:
|
||||
self.chars = self.config.getint(self.profile, config_key)
|
||||
else:
|
||||
if self.chars == None and self.config.has_option(self.profile, 'chars'):
|
||||
self.chars = self.config.getint(self.profile, 'chars')
|
||||
self.config.set(self.profile, config_key, self.chars)
|
||||
self.config.set(self.profile, config_key, str(self.chars))
|
||||
self.writeconfig()
|
||||
|
||||
if self.chars < 4 or self.chars > 26:
|
||||
print 'invalid password length value from configuration using default'
|
||||
print('invalid password length value from configuration using default')
|
||||
self.chars = 12
|
||||
|
||||
return self.chars
|
||||
|
||||
def get_passord_type(self):
|
||||
config_key = '%s_password_type' % self.tag
|
||||
config_key = f'{self.tag}_password_type'
|
||||
|
||||
if self.config.has_option(self.profile, config_key) and self.pass_type == None:
|
||||
self.pass_type = self.config.getint(self.profile, config_key)
|
||||
|
@ -134,13 +135,14 @@ class Util(object):
|
|||
if self.pass_type == None and self.config.has_option(self.profile, 'password_type'):
|
||||
self.pass_type = self.config.getint(self.profile, 'password_type')
|
||||
|
||||
self.config.set(self.profile, config_key, self.pass_type)
|
||||
self.config.set(self.profile, config_key, str(self.pass_type))
|
||||
self.writeconfig()
|
||||
|
||||
if self.pass_type < 1 or self.pass_type > 3:
|
||||
print 'invalid password type value from configuration using default'
|
||||
print('invalid password type value from configuration using default')
|
||||
self.pass_type = 1
|
||||
|
||||
return self.pass_type
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
|
|
Loading…
Reference in New Issue