AnyankaKeys/Python/AnyankaKeys.py
2026-02-16 06:55:51 +01:00

205 lines
7.1 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Any, Self, Callable, Optional, TypeVar, Iterable
from time import time
from re import compile as re_compile, Pattern as RePattern, I as RE_IgnoreCase
T = TypeVar("T", int, float, str, bytes)
class AnyankaKeys:
__slots__:tuple[str] = (
'__alphabet', '__dictionary', '__private_key', '__private_key_l',
'__multiplier', '__primes', '__primes_l', '__multiplier_jumps',
'__multiplier_jump', '__base', '__encrypt_i', '__password', '__password_l'
)
ALPHABET:tuple[str] = tuple("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
PRIVATE_KEY:tuple[int] = tuple(range(1, 0x100))
MULTIPLIER:int = 1
MULTIPLIER_JUMPS:int = 3
MULTIPLIER_JUMP:int = 7
PRIMES:tuple[int] = (
0x3FFFFFFB, 0x3FFFFF29, 0x3FFFFF0B,
0x2FFFFFFF, 0x2FFFFF5B, 0x1FFFFFFF,
0x279DB13D, 0x279DB113,
0x2AAAAAAB, 0x1555556B, 0x27D4EB2F, 0x165667B1,
0x1000007F, 0x3B9ACA07, 0x01000193, 0x1EADBEEF, 0x0AFEBABE, 0x0BADC0DE, 0x3B9AC9C1, 0x1D295C4D, 0x990BF9F, 0x1CFAA2DB,
0xDEADBEEF, 0xCAFEBABF, 0xBAADF00D
)
RE_KEY:RePattern = re_compile(r'^[a-z_][a-z0-9_]*$', RE_IgnoreCase)
def __init__(self:Self, inputs:Optional[dict[str, Any|None]] = None) -> None:
self.__alphabet:tuple[str] = tuple(self.unique(self.get_value("alphabet", inputs, self.ALPHABET)))
self.__dictionary:dict[str, int] = {value : index for index, value in enumerate(self.__alphabet)}
self.__private_key:tuple[int] = tuple(self.get_value("private_key", inputs, self.PRIVATE_KEY))
self.__private_key_l:int = len(self.__private_key)
self.__multiplier:int = self.get_value("multiplier", inputs, self.MULTIPLIER)
self.__primes:tuple[int] = tuple(self.get_value("primes", inputs, self.PRIMES))
self.__primes_l:int = len(self.__primes)
self.__multiplier_jumps:int = self.get_value("multiplier_jumps", inputs, self.MULTIPLIER_JUMPS)
self.__multiplier_jump:int = self.get_value("multiplier_jump", inputs, self.MULTIPLIER_JUMP)
l:int = len(self.__alphabet)
self.__base:int = self.get_value("base", inputs, l)
self.__encrypt_i:int = 0
self.__password:tuple[int] = (0,)
self.__password_l:int = 1
self.set_password(self.get_value("password", inputs, ""))
if self.__base > l:
self.__base = l
def set_password(self:Self, password:str) -> None:
if password:
password_changed:list[int] = []
self.change_base(password, self.__base, input_handler = ord, output_handler = password_changed.append)
self.__password = tuple(password_changed)
else:
self.__password = (0,)
self.__password_l = len(self.__password)
def __get_multiplier(self:Self, i:int) -> int:
value:int = (i + self.__multiplier + self.__primes[
i := (i + self.__multiplier_jump) % self.__primes_l
]) & 0x3FFFFFFF
for _ in range(self.__multiplier_jumps):
shift:int = 13 + i % 8
value = ((value ^ (
value >> shift if i & 1 else value << shift
)) + self.__primes[
i := (i + self.__multiplier_jump) % self.__primes_l
]) & 0x3FFFFFFF
return value
def encrypt(self:Self, data:str) -> str:
i:int = self.__get_multiplier(self.__encrypt_i + len(data) + int(time() % 1 * 1000)) % self.__base
summatory:str = self.__alphabet[i]
encrypted:list[str] = []
self.__encrypt_i += i
i -= 1
def output_handler(value:int) -> None:
nonlocal encrypted, i
multiplier:int = self.__get_multiplier(i := i + 1)
encrypted.append(self.__alphabet[(multiplier + value + self.__private_key[
multiplier // self.__base % self.__private_key_l
] + self.__password[multiplier % self.__password_l]) % self.__base])
self.change_base(data, self.__base, 0x100,
input_handler = ord,
output_handler = output_handler
)
return summatory + "".join(reversed(encrypted))
def decrypt(self:Self, data:str) -> str:
i:int = len(data[1:]) + self.__dictionary[data[0]]
decrypted:list[str] = []
def output_handler(value:int) -> None:
nonlocal decrypted
decrypted.append(chr(value))
def input_handler(value:str) -> int:
nonlocal i
multiplier:int = self.__get_multiplier(i := i - 1)
return (self.__dictionary[value] - self.__private_key[
multiplier // self.__base % self.__private_key_l
] - multiplier - self.__password[multiplier % self.__password_l]) % self.__base
self.change_base(data[1:], 0x100, self.__base,
input_handler = input_handler,
output_handler = output_handler
)
return "".join(reversed(decrypted))
@classmethod
def get_keys(cls:type[Self], *inputs:Iterable[Any|None]) -> list[str]:
keys:list[str] = []
for item in inputs:
if isinstance(item, str):
cls.RE_KEY.match(item) and item in keys or keys.append(item)
elif isinstance(item, (list, tuple)):
keys.extend(cls.get_keys(*item))
return keys
@classmethod
def get_dictionaries(cls:type[Self], *inputs:Iterable[Any|None]) -> list[dict[str, Any|None]]:
dictionaries:list[dict[str, Any|None]] = []
for item in inputs:
if isinstance(item, dict):
dictionaries.append(item)
elif isinstance(item, (list, tuple)):
dictionaries.extend(cls.get_dictionaries(*item))
return dictionaries
@classmethod
def get_value(
cls:type[Self],
keys:str|list[str]|tuple[str, ...],
inputs:dict[str, Any|None]|Iterable[Any|None],
default:Optional[Any] = None
) -> Any|None:
if len(keys := cls.get_keys(keys)):
for dictionary in cls.get_dictionaries(inputs):
for key in keys:
if key in dictionary:
return dictionary[key]
return default
@staticmethod
def unique(items:Iterable[Any|None]) -> list[Any|None]:
return list(dict.fromkeys(items))
@staticmethod
def change_base(
data:Iterable[T],
to_base:int,
from_base:int = 0x100,
input_handler:Optional[Callable[[T], int]] = None,
output_handler:Optional[Callable[[int], None]] = None
) -> None:
stack:int = 0
value:int
has:bool = False
if input_handler is None:input_handler = lambda value:value
if output_handler is None:output_handler = lambda value:value
for value in data:
stack = stack * from_base + input_handler(value)
while stack >= to_base:
has = True
stack, value = divmod(stack, to_base)
output_handler(value)
(not has or stack) and output_handler(stack)