import random

isprime = lambda number: all(number % i for i in range(2, number))


class RSA:

    e = 3

    def __init__(self, *args, **kwargs):
        self.initialize(*args, **kwargs)

    def initialize(self, *args, **kwargs):
        if args: self.p, self.q = args
        else:
            kwargs = kwargs or {'start': 100, 'end':400}
            simples = [i for i in range(kwargs['start'], kwargs['end']) if isprime(i)]
            self.p = random.choice(simples)
            while True:
                self.q = random.choice(simples)
                if self.q != self.p: break;

            print (self.p, self.q)
        self.n = self.q * self.p
        self.euler_value = (self.p-1)*(self.q-1)

        if not self.create_secret_key():
            if args:
                arg = int(input('Worth p/q pair for secret_exp calculate. Input other q value: '))
                self.initialize(args[0], arg)
            else:
                self.initialize()

    def create_secret_key(self, start=100, end=100000):

        for i in range(start, end):
            if (i * self.e) % self.euler_value == 1:
                self.secret_exp = i
                return self.secret_exp, self.n
        return None


    generate_open_key = lambda self: (self.e, self.n,)

    encrypt_value = lambda self, value: (value ** self.e) % self.n
    decrypt_value = lambda self, value: (value ** self.secret_exp) % self.n


def main():
    rsa = RSA()

    print(rsa)
    # s_key = rsa.create_secret_key()
    s_key = rsa.secret_exp

    print(s_key)
    o_key = rsa.generate_open_key()

    print(o_key)

    val = int(input("Enter value for decryption: ")) or 111111


    enc_value = (rsa.encrypt_value(val))
    print (enc_value)

    input("Enter any key for decryption ")

    print(rsa.decrypt_value(enc_value))

    # print( isprime(6111579))

if __name__ == '__main__':
    main()