Code

This is a simplified/generalized version of the core underlying code of the cipher. Full disclosure, for this challenge I generated my own encryption/decryption key equations which are much more complex than what the following code generates.

import hashlib
import hmac
import secrets
import os

class SIMBA():
    """Simple, Iterative-Math Based Algorithm"""

    enc_operations = ['*','+','^','-','//']
    dec_operations = enc_operations[::-1]

    def __init__(self, random_rounds: bool = False) -> None:
        # get environment variables
        encryption_key = os.environ['SIMBA_ENCRYPTION_KEY'] if os.environ.get('SIMBA_ENCRYPTION_KEY') is not None else 'x'
        decryption_key = os.environ['SIMBA_DECRYPTION_KEY'] if os.environ.get('SIMBA_DECRYPTION_KEY') is not None else 'x'
        hmac_key = os.environ['SIMBA_HMAC_KEY'] if os.environ.get('SIMBA_HMAC_KEY') is not None else secrets.token_hex(32)

        # generate variables if none exist
        if encryption_key == 'x' or decryption_key == 'x':
            # generate random operations and numbers
            on_list = []
            for _ in range(secrets.randbelow(16) + 17):
                o = secrets.randbelow(len(self.enc_operations)-1)
                n = self.number(o)
                on_list.append({'o':o,'n':n})

            # generate encryption key
            for on in on_list:
                encryption_key = self.alg(encryption_key, on['o'], on['n'], self.enc_operations)

            # generate decryption key
            for on in reversed(on_list):
                decryption_key = self.alg(decryption_key, on['o'], on['n'], self.dec_operations)

        # set variables
        self.random_rounds = random_rounds   
        self.encryption_key = encryption_key
        self.decryption_key = decryption_key
        self.hmac_key = hmac_key

    def hmac(self, s: str):
        """Returns an HMAC signature of the encrypted message"""
        return hmac.new(self.hmac_key.encode('ascii'),
                        s.encode('ascii'),
                        hashlib.sha256).hexdigest()

    def number(self, o: int):
        """Generates a random number for the algorithm and
        adds extra complexity for certain operations"""
        n = secrets.randbelow((2**32 if o == 2 else (2**10 if (o&1) else 2**7))) + 1
        extra = f"*(-1)**(i+{secrets.randbelow(2)})" if (o&1) and secrets.randbelow(2) else ""
        return f"({n}{extra})"

    def alg(self, x: str, o: int, n: str, operations: list):
        """Returns a string representation of an algebraic equation"""
        return f"({x}{operations[o]}{n})"

    def ascii_to_bin(self, s: str):
        """Converts an ascii string to a binary string"""
        return ''.join('{:08b}'.format(i) for i in bytearray(s, 'ascii'))

    def int_to_str(self, x: int):
        """Converts an integer to a binary string and the
        converts the binary string to a text string"""
        b = format(x, 'b')
        # ensure leading zeroes are added
        b = b.zfill(len(b) + (8 - len(b) % 8))
        return ''.join([chr(int(b[i:i+8],2)) for i in range(0,len(b),8)])

    def sum_digits(self, x: int):
        """Sums the digits of an integer"""
        sum = 0
        for digit in str(x): 
            sum += int(digit)     
        return sum

    def encrypt(self, s: str):
        """Encrypts plaintext by converting the binary to a number and
        iterating that number through the encryption_key equation"""
        try:
            # convert string to int
            b = self.ascii_to_bin(s)
            x = int(b, 2)

            # iterative encryption
            rounds = secrets.randbelow(191) + 64 if self.random_rounds else (self.sum_digits(x) % 191) + 64
            for i in range(1, rounds + 1):
                x = eval(self.encryption_key)
            x = int(format(x, 'x') + format(rounds, 'x'), 16)

            # final iteration to hide rounds
            i = 1
            x = eval(self.encryption_key)
            msg = format(x, 'x')

            return msg + self.hmac(msg)
        except:
            return "Something went wrong..."

    def decrypt(self, s: str):
        """Decrypts ciphertext by iterating the number through the decryption_key
        equation and converting resulting binary number to a text string"""
        try:
            hash = s[-64:]
            sx = s[:-64]
            if self.hmac(sx) == hash:
                # decrypt final iteration to get rounds
                i = 1
                x = int(sx, 16)
                x = eval(self.decryption_key)
                sx = format(x, 'x')

                # iterative decryption
                rounds = int(sx[-2:], 16)
                x = int(sx[:-2], 16)
                for i in reversed(range(1, rounds + 1)):
                    x = eval(self.decryption_key)

                # convert to string
                return self.int_to_str(x)
            else:
                raise Exception
        except:
            return "Improperly encrypted ciphertext."

if __name__ == "main":
    pt = "This is a test message!"
    
    # test without random rounds
    s1 = SIMBA()
    ct1 = s1.encrypt(pt)
    print('W/O Random Rounds:', ct1, s1.decrypt(ct1))

    # test with random rounds
    s2 = SIMBA(True)
    # example 1
    ct2 = s2.encrypt(pt)
    print('Random Rounds 1:', ct2, s2.decrypt(ct2))
    # example 2
    ct3 = s2.encrypt(pt)
    print('Random Rounds 2:', ct3, s2.decrypt(ct3))