diff --git a/creatorUtils/__init__.py b/creatorUtils/__init__.py index 217a66b..90e950f 100644 --- a/creatorUtils/__init__.py +++ b/creatorUtils/__init__.py @@ -1,4 +1,9 @@ __all__ = [ + '__all__', + '__author__', + '__version__', + 'base64', + 'canceler', 'compat', 'crypt', 'dotNum', @@ -7,3 +12,6 @@ 'path', 'rounder', ]; +__author__ = 'Ken Peterson A.K.A. The Elemental of Creation'; +__url__ = 'https://github.com/TheElementalOfCreation'; +__version__ = '0.2.1'; diff --git a/creatorUtils/base64.py b/creatorUtils/base64.py new file mode 100644 index 0000000..28cb7d2 --- /dev/null +++ b/creatorUtils/base64.py @@ -0,0 +1,16 @@ +import base64; +import string; + +DEFAULT_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + +def b64decode(s, altchars = {}): + if isinstance(altchars, dict): + altchars = (''.join(altchars.keys()), ''.join(altchars.values())); + s = s.translate(string.maketrans(*altchars[::-1])); + return base64.b64decode(s); + +def b64encode(s, altchars = None): + if isinstance(altchars, dict): + altchars = (''.join(altchars.keys()), ''.join(altchars.values())); + s = base64.b64encode(s); + return s.translate(string.maketrans(*altchars)); diff --git a/creatorUtils/canceler.py b/creatorUtils/canceler.py new file mode 100644 index 0000000..75e726f --- /dev/null +++ b/creatorUtils/canceler.py @@ -0,0 +1,16 @@ +class Canceler(object): + def __init__(self, fake = False): + self.__can = False; + self.__fake = fake; + + def cancel(self): + if not self.__fake: + self.__can = True; + + def get(self): + return self.__can; + + def reset(self): + self.__can = False; + +FAKE = Canceler(True); diff --git a/creatorUtils/compat/progress_bar.py b/creatorUtils/compat/progress_bar.py index 91c6494..d09d48d 100644 --- a/creatorUtils/compat/progress_bar.py +++ b/creatorUtils/compat/progress_bar.py @@ -9,21 +9,16 @@ cannot, it will define the necessary classes. """ import sys; +class Dummy(object): + def __init__(self, *args, **kwargs): + object.__init__(self); + def __call__(self, inp): + return inp; try: from progressbar import *; __isRealProgressBar__ = True; except: __isRealProgressBar__ = False; - if sys.version_info[0] < 3: - h = ''; - else: - h = '2'; - print('Could not import progressbar{} module! Disabling progress bars...'.format(h)); - del h; - - class ProgressBar(object): - def __init__(self, *args, **kwargs): - object.__init__(self); - def __call__(self, inp): - return inp; + print('Could not import progressbar module! Disabling progress bars...'); + ProgressBar = Dummy; diff --git a/creatorUtils/compat/structures.py b/creatorUtils/compat/structures.py index c836d71..78844f6 100644 --- a/creatorUtils/compat/structures.py +++ b/creatorUtils/compat/structures.py @@ -6,6 +6,7 @@ class RepeatingGenerator(object): Returns an entry in the list, starting from the first, and looping to the beginning when the end is reached """ def __init__(self, data_list): + print('WARNING: You probably want to use itertools.cycle instead of this class.') object.__init__(self); if not isinstance(data_list, list_types): raise TypeError('`data_list` must either be a list or tuple.'); @@ -30,3 +31,51 @@ def length(self): @property def position(self): return self.__position; + + + +try: + import itertools; + repeater = itertools.cycle; +except ModuleNotFoundError: + repeater = RepeatingGenerator; + + + +# class Byte(tuple): +# def __new__(tupletype, integer): +# return tuple.__new__(tupletype, [int(x) for x in bin(integer)[2:].rjust(8, '0')]) +# +# BYTES = tuple([Byte(x) for x in range(256)]); +# +# if version_info[0] < 3: +# def toArrayOfBytes(inp): +# if isinstance(inp, bytearray): +# return [BYTES[x] for x in inp]; +# elif isinstance(inp, str): +# return [BYTES[ord(x)] for x in inp]; +# elif isinstance(inp, ImmutableBitArray): +# return inp; +# else: +# raise TypeError('Input must be either a bytearray or string.'); +# +# else: +# def toArrayOfBytes(inp): +# if isinstance(inp, bytes): +# return [BYTES[x] for x in inp]; +# else: +# raise TypeError('Input must be either a bytearray or string.'); +# +# +# class BitArray(object): +# def __init__(self, inp): +# object.__init__(self): +# +# def __add__(self, inp): +# +# +# +# +# class ImmutableBitArray(tuple): +# def __new__(tupletype, inp): +# return tuple.__new__(tupletype, toArrayOfBytes(inp)); diff --git a/creatorUtils/compat/types.py b/creatorUtils/compat/types.py index 49ceda2..f1962bf 100644 --- a/creatorUtils/compat/types.py +++ b/creatorUtils/compat/types.py @@ -20,15 +20,17 @@ `isinstance(var, intlong)` """ -import sys; +from sys import version_info; -if sys.version_info[0] < 3: +if version_info[0] < 3: + ModuleNotFoundError = ImportError; stringType = (str, unicode); intlong = (int, long); bytes = bytearray; else: - stringType = [str]; - intlong = [int]; + bytes = bytes; + stringType = (str,); + intlong = (int,); import io; file = io.IOBase; @@ -37,4 +39,7 @@ def a(): function = a.__class__; builtin_function = hex.__class__; +method = __builtins__.type.__init__.__class__; +module = __builtins__.__class__; +functionType = (function, builtin_function, __builtins__.classmethod, method); list_types = (list, tuple); diff --git a/creatorUtils/crypt/WebSocket.py b/creatorUtils/crypt/WebSocket.py index 8f42ce1..1ad7724 100644 --- a/creatorUtils/crypt/WebSocket.py +++ b/creatorUtils/crypt/WebSocket.py @@ -1,4 +1,5 @@ import base64; +import gc; import hashlib; import zlib; import struct; @@ -147,16 +148,23 @@ def __init__(self, *args, **kwargs): self.regenCompObj(); def regenCompObj(self): + try: + del self.__zlib; + except: + pass; + gc.collect(); self.__zlib = zlib.decompressobj(*self.__options[0], **self.__options[1]); def inflate(self, data): try: a = self.__zlib.decompress(data + '\x00\x00\xff\xff'); a += self.__zlib.flush(); - except: + return a; + except Exception as e: + print(e); self.regenCompObj(); a = self.__zlib.decompress(data + '\x00\x00\xff\xff'); a += self.__zlib.flush(); - return a; + return a; decompress = inflate; diff --git a/creatorUtils/crypt/main.py b/creatorUtils/crypt/main.py index 5643bf2..785d301 100644 --- a/creatorUtils/crypt/main.py +++ b/creatorUtils/crypt/main.py @@ -3,19 +3,26 @@ import os; import random; import sys; -from creatorUtils.compat import progress_bar, structures; +from creatorUtils.compat import progress_bar; +from creatorUtils.compat import structures; from creatorUtils.compat.types import *; +def create_hash(name, data): + HASH_FUNCTIONS[name][0](*HASH_FUNCTIONS[name], data); alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + def insecure(algorithm): - print('WARNING: Selected method "{}" is considered to be insecure. Use at your own risk.'.format(algorithm)); + print('WARNING: Selected method "' + algorithm + '" is considered to be insecure. Use at your own risk.'); def secure(algorithm): pass; def unknown(algorithm): - print('WARNING: Unrecognized algorithm "{}". It may be insecure.'.format(algorithm)); + print('WARNING: Unrecognized algorithm "' + algorithm + '". It may be insecure.'); + +def hashlib_hash_functions(method, data): + return hashlib.new(method, data).digest() # Define Constants MD4 = 'MD4'; @@ -49,9 +56,16 @@ def unknown(algorithm): WHIRLPOOL: secure }; -def generate_new_random(key): - #TODO - pass; +HASH_FUNCTIONS = { + MD4: (hashlib_hash_functions, (MD4,)), + MD5: (hashlib_hash_functions, (MD5,)), + SHA1: (hashlib_hash_functions, (SHA1,)), + SHA224: (hashlib_hash_functions, (SHA224,)), + SHA256: (hashlib_hash_functions, (SHA256,)), + SHA384: (hashlib_hash_functions, (SHA384,)), + SHA512: (hashlib_hash_functions, (SHA512,)), + WHIRLPOOL: (hashlib_hash_functions, (WHIRLPOOL,)) +} def randStr(length): """ @@ -72,7 +86,7 @@ def __init__(self, string_or_bytes, encoding = None, methods = [SHA512]): for x in methods: HASH_METHOD_WARNING.get(x, unknown)(x); self.__originalData = string_or_bytes if isinstance(string_or_bytes, bytes) else bytes(string_or_bytes, encoding = encoding); - self.__method = structures.RepeatingGenerator(methods); + self.__method = structures.repeater(methods); self.__currentData = bytes(hashlib.new(self.__method(), self.__originalData).digest()); self.__position = 0; @@ -82,7 +96,7 @@ def gen(self, length): a += self.__currentData[self.__position:self.__position + g]; remaining = length - len(a); while remaining: - self.__currentData = bytes(hashlib.new(self.__method(), self.__currentData).digest()); + self.__currentData = bytes(create_hash(self.__method(), self.__currentData)); curlen = len(self.__currentData); if remaining <= curlen: self.__position = remaining; @@ -112,7 +126,7 @@ def bxor(inp, key): def crypt_string(data, key, encoding): """ - Encrypts the string "data" with "key". + Encrypts the string `data` with `key`. Both should be a string with the same encoding. Returns a bytes object. @@ -141,7 +155,7 @@ def randXOR(data, key, r = None, start = 0): return bytes([data[i] ^ key1[i] ^ rand[i] for i in range(dlen)]); -def file(path1, key, pagesize = 262144, rand = True, overwrite = False, hash_methods = [SHA512, SHA256, MD5, WHIRLPOOL]): +def crypt_file(path1, key, pagesize = 262144, rand = True, overwrite = False, hash_methods = [SHA512, SHA256, MD5, WHIRLPOOL]): """ Function to encrypt whole files. + "path1" is the path to the file to be encrypted. @@ -191,3 +205,27 @@ def file(path1, key, pagesize = 262144, rand = True, overwrite = False, hash_met os.rename(nm, path1); else: os.rename(nm, path1 + '.crypt'); + + + +def add_new_hash_method(name, security, hash_function, args): + """ + Use to define a new type of hash function. Provide the name, + one of the security functions (secure, insecure, unknown), + the function to do the hash, and any arguments that come + before the data input. + """ + if not isinstance(name, stringType): + raise TypeError('Name must be a string.'); + if len(name) == 0: + raise ValueError('Name must be at least one character long.'); + if not isinstance(security, functionType): + + # No issues with the inputs themselves + if name in HASH_METHODS: + raise Exception('Method already exists: '+ name); + + # Seems to be valid, and does not already exist + HASH_METHODS.append(name); + HASH_METHOD_WARNING[name] = security; + HASH_FUNCTIONS[name] = (hash_function, tuple(args)); diff --git a/creatorUtils/path.py b/creatorUtils/path.py index d46cf52..513413d 100644 --- a/creatorUtils/path.py +++ b/creatorUtils/path.py @@ -71,7 +71,7 @@ def getall(inp, specExt = True, ext = ['msg'], extsep = '.', progressBar = None, c = []; v = os.walk(inp, onerror = onerror); if progressBar == None: - progressBar = pb.ProgressBar(); + progressBar = pb.Dummy(); iterator = progressBar(v); isfile = True; try: @@ -135,7 +135,7 @@ def isFile(inp): if os.path.exists(inp): return os.path.isfile(inp); else: - raise OSError('Cannot find the path specified: "{}"'.format(inp)); + raise OSError('Cannot find the path specified: "' + inp + '"'); def isFolder(inp): """ @@ -146,7 +146,7 @@ def isFolder(inp): if os.path.exists(inp): return os.path.isdir(inp); else: - raise OSError('Cannot find the path specified: "{}"'.format(inp)); + raise OSError('Cannot find the path specified: "' + inp + '"'); def split(inp): """ diff --git a/setup.py b/setup.py index 32bae32..63aecfe 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name = "creatorUtils", - version = "0.2.0", + version = "0.2.1", author = "The Elemental of Creation", author_email = "arceusthe@gmail.com", description = "creatorUtils main package",