Python Forum

Full Version: RSA Cipher with blocks
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi, I really need help. I need to create encryption using block access after 10 characters and with lower_limit = 10 ** 11 and upper_limit = 10 ** 12, but I don't know how to do it. I created two codes, each of which only works from scratch and I don't know how to make it work well. The first code works fine for any character length, but it doesn't work for more than 8 bits and n must be lower_limit = 10 ** 12 and upper_limit = 10 ** 13. Code 2 only works for a maximum of 8 characters, but it also works for 9 bit and for n lower_limit = 10 ** 11 and upper_limit = 10 ** 12.


Code 1
import random
from math import gcd
from sympy import mod_inverse, isprime

class SimpleRSA:
    def __init__(self):
        self.public_key = None
        self.private_key = None

    def generate_keypair(self):
        if self.public_key is not None and self.private_key is not None:
            return

        p = self.generate_large_prime()
        q = self.generate_large_prime()

        n = p * q
        phi = (p - 1) * (q - 1)

        e = random.randint(2, phi - 1)
        while gcd(e, phi) != 1:
            e = random.randint(2, phi - 1)

        d = mod_inverse(e, phi)

        self.public_key = (n, e)
        self.private_key = (n, d)

        return self.public_key, self.private_key

    def generate_large_prime(self):
        lower_limit = 10 ** 12
        upper_limit = 10 ** 13
        potential_prime = random.randint(lower_limit, upper_limit)
        while not isprime(potential_prime):
            potential_prime = random.randint(lower_limit, upper_limit)
        return potential_prime

    def encrypt(self, message):
        n, e = self.public_key
        binary_blocks = self.text_to_numeric_binary_blocks(message)

        print(f"binary_blocks: {binary_blocks}")

        encrypted_blocks = [pow(int(block, 2), e, n) for block in binary_blocks]

        print(f"encrypted_blocks: {encrypted_blocks}")

        return encrypted_blocks

    def decrypt(self, encrypted_blocks):
        n, d = self.private_key

        decrypted_blocks = [format(pow(block, d, n), '0b') for block in encrypted_blocks]

        print(f"decrypted_blocks: {decrypted_blocks}")

        decrypted_message = self.numeric_to_text_binary_blocks(decrypted_blocks)

        print(f"decrypted_message: {decrypted_message}")

        return decrypted_message


    def text_to_numeric_binary_blocks(self, text, block_size=10):
        binary_blocks = [
            ''.join(format(ord(char), '08b') for char in text[i:i + block_size]).rjust(block_size * 8, '0')
            for i in range(0, len(text), block_size)
        ]
        return binary_blocks

    def numeric_to_text_binary_blocks(self, binary_blocks):
        bytes_list = [int(block, 2).to_bytes((len(block) + 7) // 8, 'big') for block in binary_blocks]
        text = b''.join(bytes_list).decode(errors='replace')
        return text


def test_encryption_decryption(message):
    rsa = SimpleRSA()
    public_key, private_key = rsa.generate_keypair()

    print(f"Public key (n): {public_key[0]}")

    print(f"Original message: {message}")

    # Encryption
    encrypted_blocks = rsa.encrypt(message)
    print(f"Encrypted blocks: {encrypted_blocks}")

    # Decryption
    decrypted_message = rsa.decrypt(encrypted_blocks)
    print(f"Decrypted message: {decrypted_message}")



if __name__ == "__main__":

    test_encryption_decryption("hello")
Code 2
import random
from sympy import isprime, gcd, mod_inverse


def text_to_numeric_binary_blocks(text):
    block_size = 10  # Set block size to 10 bits
    numeric_decimal_blocks = []

    for i in range(0, len(text), block_size):
        block = text[i:i + block_size]
        numeric_decimal_block = int(''.join(format(ord(char), '010b') for char in block), 2)
        numeric_decimal_blocks.append(numeric_decimal_block)

    numeric_binary_blocks = [format(block, '010b') for block in numeric_decimal_blocks]

    return numeric_decimal_blocks, numeric_binary_blocks


def numeric_to_text_binary_blocks(numeric_decimal_blocks):
    # Convert each numeric block to a string and then concatenate them
    numeric_representation = ''.join(map(str, numeric_decimal_blocks))
    # Convert the combined string to an integer
    numeric_representation = int(numeric_representation)
    # Convert the integer to binary representation
    binary_representation = format(numeric_representation, 'b')

    # Pad the binary representation to ensure a multiple of 10 for ASCII conversion
    binary_representation = binary_representation.rjust(((len(binary_representation) + 9) // 10) * 10, '0')

    # Convert each 10-bit chunk back to an integer and then to its ASCII character
    text = ''.join(chr(int(binary_representation[i:i + 10], 2)) for i in range(0, len(binary_representation), 10))

    return text, numeric_decimal_blocks


def generate_keypair():
    p = generate_large_prime()
    q = generate_large_prime()

    n = p * q
    phi = (p - 1) * (q - 1)

    e = random.randint(2, phi - 1)
    while gcd(e, phi) != 1:
        e = random.randint(2, phi - 1)

    d = mod_inverse(e, phi)

    global public_key, private_key
    public_key = (n, e)
    private_key = (n, d)

    private_key_str = f"{private_key[0]} {private_key[1]}"
    public_key_str = f"{public_key[0]} {public_key[1]}"


def generate_large_prime():
    lower_limit = 10 ** 11
    upper_limit = 10 ** 12
    potential_prime = random.randint(lower_limit, upper_limit)
    while not isprime(potential_prime):
        potential_prime = random.randint(lower_limit, upper_limit)
    return potential_prime


def encrypt(message, public_key):
    n, e = public_key
    numeric_decimal_blocks, _ = text_to_numeric_binary_blocks(message)

    # Encrypt each block using the public key
    encrypted_blocks = [pow(block, e, n) for block in numeric_decimal_blocks]

    return encrypted_blocks


def decrypt(encrypted_blocks, private_key):
    n, d = private_key

    # Decrypt each block using the private key
    decrypted_blocks = [pow(block, d, n) for block in encrypted_blocks]

    # Convert the numeric blocks back to text
    decrypted_message, _ = numeric_to_text_binary_blocks(decrypted_blocks)

    return decrypted_message

generate_keypair()

# Example usage:
message_to_encrypt = "hello"
encrypted_blocks = encrypt(message_to_encrypt, public_key)
decrypted_message = decrypt(encrypted_blocks, private_key)

print("Original Message:", message_to_encrypt)
print("Encrypted Blocks:", encrypted_blocks)
print("Decrypted Message:", decrypted_message)