"""Wrapper to the POSIX crypt library call and associated functionality. Note that the ``methods`` and ``METHOD_*`` attributes are non-standard extensions to Python 2.7, backported from 3.3""" import _crypt import string as _string from random import SystemRandom as _SystemRandom from collections import namedtuple as _namedtuple _saltchars = _string.ascii_letters + _string.digits + './' _sr = _SystemRandom() class _Method(_namedtuple('_Method', 'name ident salt_chars total_size')): """Class representing a salt method per the Modular Crypt Format or the legacy 2-character crypt method.""" def __repr__(self): return '<crypt.METHOD_%s>' % self.name def mksalt(method=None): """Generate a salt for the specified method. If not specified, the strongest available method will be used. This is a non-standard extension to Python 2.7, backported from 3.3 """
_VERSION = b'\x00\x01' _ENC_METHOD = b'\x00\x01' #------------------------------------------------------- def utc_ts(): return datetime.datetime.now(tz=datetime.timezone.utc).timestamp() def _utc_msts48(): return int(utc_ts() * 1000) & (2**48 - 1) sys_randint = _SystemRandom().randint # returns n with a <= n <= b def pw_lifetime(): return sys_randint(400 * 86400, 600 * 86400) _salt_count = sys_randint(0, 2**32 - 1) def gen_salt(n): global _salt_count if n <= 10: return os.urandom(n) _salt_count = _salt_count + 1 if _salt_count < 2**32 - 1 else 0 return b''.join((_utc_msts48().to_bytes(6, 'little'),
from __future__ import division, print_function from collections import namedtuple as _namedtuple from random import SystemRandom as _SystemRandom import argparse import getpass import hashlib import re import sys _BASE64_CHARACTERS = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' _SALT_RE = re.compile( r'\$(?P<algo>\d)\$(?:rounds=(?P<rounds>\d+)\$)?(?P<salt>.{1,16})') _ROUNDS_DEFAULT = 5000 # As used by crypt(3) _PY2 = sys.version_info < (3, 0, 0) _sr = _SystemRandom() class _Method(_namedtuple('_Method', 'name ident salt_chars total_size')): """Class representing a salt method per the Modular Crypt Format or the legacy 2-character crypt method.""" def __repr__(self): return '<crypt.METHOD_{0}>'.format(self.name) # available salting/crypto methods METHOD_SHA256 = _Method('SHA256', '5', 16, 63) METHOD_SHA512 = _Method('SHA512', '6', 16, 106) methods = ( METHOD_SHA512,
#see https://stackoverflow.com/questions/1785503/when-should-i-use-uuid-uuid1-vs-uuid-uuid4-in-python #https://stackoverflow.com/questions/703035/when-are-you-truly-forced-to-use-uuid-as-part-of-the-design/786541#786541 from uuid import uuid1 as _uuid1 _int_from_bytes = int.from_bytes # py3 only from random import SystemRandom as _SystemRandom _system_random = _SystemRandom() def uuid1mc(): ''' This is v1 with random MAC ("v1mc"). This is a hybrid between version 1 & version 4. Version 1 UUIDs use the network card's MAC address (which unless spoofed, should be unique), plus a timestamp, plus the usual bit-twiddling to generate the UUID. Version 4 UUIDs Generate a random UUID. uuid1mc() is deliberately generating v1 UUIDs with a random broadcast MAC address (this is allowed by the v1 spec). The resulting v1 UUID is time dependant (like regular v1), but lacks all host-specific information (like v4). It's also much closer to v4 in it's collision-resistance: v1mc = 60 bits of time + 61 random bits = 121 unique bits; v4 = 122 random bits. Note: somebody reported that ran into trouble using UUID1 in Amazon EC2 instances. He use UUID1 for a database upgrade script where he generated ~120k UUIDs within a couple of minutes. The UUID collision led to violation of a primary key constraint. He suspect poor clock resolution and switching to UUID4 solved it for him. '''