def __init__(self, key=random.getrandbits(KEY_SIZE)):
        self.key = key  # random.getrandbits(KEY_SIZE)
        self.scheduler = IDEA_Key_Scheduler(self.key)
        self.enc_sub_keys, self.dec_sub_keys = self.schedule_keys()

        # self.mul = lambda x, y: int(np.mod(x * y, 2 ** BLOCK_SIZE + 1))
        self.add = lambda x, y: int(np.mod(x + y, 2**BLOCK_SIZE))
        self.xor = lambda x, y: x ^ y
Esempio n. 2
0
 def __init__(self, key=secrets.randbits(128), log=False):
     self.key = key
     self.scheduler = IDEA_Key_Scheduler(self.key)
     self.enc_sub_keys, self.dec_sub_keys = self.schedule_keys()
     self.log = log
     self.mul = lambda x, y: (x * y) % (
         2**BLOCK_SIZE + 1)  # int(np.mod(x * y, 2 ** BLOCK_SIZE + 1))
     self.add = lambda x, y: (x + y) % (
         2**BLOCK_SIZE)  # int(np.mod(x + y, 2 ** BLOCK_SIZE))
     self.xor = lambda x, y: x ^ y
class IDEA:
    def __init__(self, key=random.getrandbits(KEY_SIZE)):
        self.key = key  # random.getrandbits(KEY_SIZE)
        self.scheduler = IDEA_Key_Scheduler(self.key)
        self.enc_sub_keys, self.dec_sub_keys = self.schedule_keys()

        # self.mul = lambda x, y: int(np.mod(x * y, 2 ** BLOCK_SIZE + 1))
        self.add = lambda x, y: int(np.mod(x + y, 2**BLOCK_SIZE))
        self.xor = lambda x, y: x ^ y

    def schedule_keys(self):  # Prepares all sub keys for the rounds
        return self.scheduler.encryption_key_schedule(
        ), self.scheduler.decryption_key_schedule()

    def mul(self, x, y):
        if x == 0:
            x = 65536
        if y == 0:
            y = 65536
        return int(np.mod(x * y, 2**BLOCK_SIZE + 1))

    def calculate_cipher(self, sub_keys, text):
        """
                X1 * K1
                X2 + K2
                X3 + K3
                X4 * K4
                Step 1 ^ Step 3
                Step 2 ^ Step 4
                Step 5 * K5
                Step 6 + Step 7
                Step 8 * K6
                Step 7 + Step 9
                Step 1 ^ Step 9
                Step 3 ^ Step 9
                Step 2 ^ Step 10
                Step 4 ^ Step 10
                The input to the next round is Step 11 || Step 13 || Step 12 || Step 14, which becomes X1 || X2 || X3 || X4.
                This swap between 12 and 13 takes place after each complete round, except the last complete round (4th round),
                where the input to the final half round is Step 11 || Step 12 || Step 13 || Step 14.
                :param text: Cipher/Plain binary text
                :param sub_keys: Decryption/Encryption Sub Keys
                :return: ciphered/deciphered text
                """
        # THIS TEST SAMPLE OUTPUT MUST MATCH https://www.geeksforgeeks.org/simplified-international-data-encryption-algorithm-idea/ output
        X = text
        K = sub_keys

        # Print sub keys
        """
        [print("BIN Sub-Key: " + str(x)) for x in K]
        print("------------")
        for lst in K:
            print("HEX Sub-Key: " + ' '.join([str(hex(int(elem, 2)))[2:] for elem in lst]))
        print("------------\n")
        """
        # for i in range(len(X)):
        #    if X[i] == 0:
        #         X[i] = 65536
        step = ['0'] * 14
        for i in range(0, ROUNDS - 1):
            # Input print
            # print("Round [" + str(i + 1) + "] BIN input " + str(X))
            # print("Round [" + str(i + 1) + "] DEC input " + str([int(x, 2) for x in X]))
            # print("Round [" + str(i + 1) + "] HEX input " + ' '.join([str(hex(int(x, 2)))[2:] for x in X]))
            # Sub Key print
            # print("Round [" + str(i + 1) + "] BIN sub-key " + str(K[i]))
            # print("Round [" + str(i + 1) + "] DEC sub-key " + str([int(k, 2) for k in K[i]]))
            # print("Round [" + str(i + 1) + "] HEX sub-key " + ' '.join([str(hex(int(k, 2)))[2:] for k in K[i]]))
            step[0] = (self.mul(int(X[0], 2), int(K[i][0], 2)))
            step[1] = (self.add(int(X[1], 2), int(K[i][1], 2)))
            step[2] = (self.add(int(X[2], 2), int(K[i][2], 2)))
            step[3] = (self.mul(int(X[3], 2), int(K[i][3], 2)))
            step[4] = (self.xor(step[0], step[2]))
            step[5] = (self.xor(step[1], step[3]))
            step[6] = (self.mul(step[4], int(K[i][4], 2)))
            step[7] = (self.add(step[5], step[6]))
            step[8] = (self.mul(step[7], int(K[i][5], 2)))
            step[9] = (self.add(step[6], step[8]))
            step[10] = (self.xor(step[0], step[8]))
            step[11] = (self.xor(step[2], step[8]))
            step[12] = (self.xor(step[1], step[9]))
            step[13] = (self.xor(step[3], step[9]))
            # for y in range(14):
            #    print("Step "+str(y)+": "+str(bin(int(step[y])))[2:] + "({0})".format(int(step[y])))

            X = [
                str(bin(int(step[10])))[2:],
                str(bin(int(step[11])))[2:],
                str(bin(int(step[12])))[2:],
                str(bin(int(step[13])))[2:]
            ]  # Swap step 12 and 13

            for j in range(0, len(X)):
                X[j] = '0' * (4 - len(X[j])) + X[j]

            # print("Round [" + str(i + 1) + "] BIN output " + str(X))
            # print("Round [" + str(i + 1) + "] DEC output " + str([int(x, 2) for x in X]))
        # print("Round [" + str(i + 1) + "] HEX output " + ' '.join([str(hex(int(x, 2)))[2:] for x in X])
        #                  + "\n---------------")
        """X1 * K1
           X2 + K2
           X3 + K3
           X4 * K4"""
        X = [
            str(bin(int(step[10])))[2:],
            str(bin(int(step[12])))[2:],
            str(bin(int(step[11])))[2:],
            str(bin(int(step[13])))[2:]
        ]
        # print("Round [" + str(ROUNDS - 0.5) + "] BIN input " + str(X))
        # print("Round [" + str(ROUNDS - 0.5) + "] DEC input " + str([int(x, 2) for x in X]))
        # print("Round [" + str(ROUNDS - 0.5) + "] HEX input " + ' '.join([str(hex(int(x, 2)))[2:] for x in X]))
        # Sub Key print
        # print("Round [" + str(ROUNDS - 0.5) + "] BIN sub-key " + str(K[i]))
        # print("Round [" + str(ROUNDS - 0.5) + "] DEC sub-key " + str([int(k, 2) for k in K[i]]))
        # print("Round [" + str(ROUNDS - 0.5) + "] HEX sub-key " + ' '.join(
        # [str(hex(int(k, 2)))[2:] for k in K[ROUNDS - 1]]))
        result = []
        result.append(self.mul(int(X[0], 2), int(K[ROUNDS - 1][0], 2)))
        result.append(self.add(int(X[1], 2), int(K[ROUNDS - 1][1], 2)))
        result.append(self.add(int(X[2], 2), int(K[ROUNDS - 1][2], 2)))
        result.append(self.mul(int(X[3], 2), int(K[ROUNDS - 1][3], 2)))

        temp = [str(hex(int(x)))[2:] for x in result]
        # print('hex: ' + str(temp))
        temp = ['0' * (4 - len(x)) + x for x in temp]
        for i in range(len(temp)):
            if temp[i] == '10000':
                temp[i] = '0000'
        # print('hex added: ' + str(temp))
        cipher = ''.join([x for x in temp])
        # print("Final Cipher/Decipher: " + cipher + "\n---------------")
        cipher = '0' * (16 - len(cipher)) + cipher
        if len(cipher) > 16:
            print('aa')
        return cipher  # Hex string

    def encrypt(self, plain_text='', is_hex=False, codec='utf-8'):
        if not is_hex:
            plain_text = plain_text.encode(codec).hex()
        plain_text = get_bin_block(plain_text)
        return self.calculate_cipher(self.enc_sub_keys, plain_text)

    def decrypt(self, cipher_text='', codec='utf-8'):
        cipher_text = get_bin_block(cipher_text)
        res = self.calculate_cipher(self.dec_sub_keys, cipher_text)
        res = ''.join('0' * (16 - len(res))) + res
        print(binascii.unhexlify(res))
        # res = bytearray.fromhex(res)#.decode(codec)
        return binascii.unhexlify(res)
Esempio n. 4
0
class IDEA:
    def __init__(self, key=secrets.randbits(128), log=False):
        self.key = key
        self.scheduler = IDEA_Key_Scheduler(self.key)
        self.enc_sub_keys, self.dec_sub_keys = self.schedule_keys()
        self.log = log
        self.mul = lambda x, y: (x * y) % (
            2**BLOCK_SIZE + 1)  # int(np.mod(x * y, 2 ** BLOCK_SIZE + 1))
        self.add = lambda x, y: (x + y) % (
            2**BLOCK_SIZE)  # int(np.mod(x + y, 2 ** BLOCK_SIZE))
        self.xor = lambda x, y: x ^ y

    def schedule_keys(self):  # Prepares all sub keys for the rounds
        return self.scheduler.encryption_key_schedule(
        ), self.scheduler.decryption_key_schedule()

    def calculate_cipher(self, sub_keys, text):
        """
                X1 * K1
                X2 + K2
                X3 + K3
                X4 * K4
                Step 1 ^ Step 3
                Step 2 ^ Step 4
                Step 5 * K5
                Step 6 + Step 7
                Step 8 * K6
                Step 7 + Step 9
                Step 1 ^ Step 9
                Step 3 ^ Step 9
                Step 2 ^ Step 10
                Step 4 ^ Step 10
                :param text: Cipher/Plain 4 16-bit blocks
                :param sub_keys: Decryption/Encryption Sub Keys [A list of 9 lists, 6 subkeys for each round,
                                    4 subkeys for the last round]
                :return: ciphered/deciphered text
                """
        X = text
        K = sub_keys

        step = ['0'] * 14
        for i in range(0, ROUNDS - 1):
            step[0] = (self.mul(X[0], int(K[i][0], 2)))
            step[1] = (self.add(X[1], int(K[i][1], 2)))
            step[2] = (self.add(X[2], int(K[i][2], 2)))
            step[3] = (self.mul(X[3], int(K[i][3], 2)))
            step[4] = (self.xor(step[0], step[2]))
            step[5] = (self.xor(step[1], step[3]))
            step[6] = (self.mul(step[4], int(K[i][4], 2)))
            step[7] = (self.add(step[5], step[6]))
            step[8] = (self.mul(step[7], int(K[i][5], 2)))
            step[9] = (self.add(step[6], step[8]))
            step[10] = (self.xor(step[0], step[8]))
            step[11] = (self.xor(step[2], step[8]))
            step[12] = (self.xor(step[1], step[9]))
            step[13] = (self.xor(step[3], step[9]))
            # [print("Step "+str(y)+": "+str(hex(int(step[y]))) + "({0})".format(int(step[y]))) for y in range(14)]

            if self.log:
                print("Round [" + str(i + 1) + "] HEX input   " +
                      ' '.join([str(hex(int(x))) for x in X]))
                print("Round [" + str(i + 1) + "] HEX sub-key " +
                      ' '.join([str(hex(int(k, 2))) for k in K[i]]))
            X = [step[10], step[11], step[12], step[13]]  # Swap step 12 and 13
            if self.log:
                print("Round [" + str(i + 1) + "] HEX output  " +
                      ' '.join([str(hex(int(x)))
                                for x in X]) + "\n---------------")
        """X1 * K1
           X2 + K2
           X3 + K3
           X4 * K4"""
        X = [step[10], step[12], step[11], step[13]]
        result = [
            self.mul(X[0], int(K[ROUNDS - 1][0], 2)),
            self.add(X[1], int(K[ROUNDS - 1][1], 2)),
            self.add(X[2], int(K[ROUNDS - 1][2], 2)),
            self.mul(X[3], int(K[ROUNDS - 1][3], 2))
        ]

        temp = [str(hex(int(x)))[2:] for x in result]
        temp = ['0' * (4 - len(x)) + x for x in temp]
        cipher = ''.join([x for x in temp])

        if self.log:
            print("Round [" + str(ROUNDS - 0.5) + "] HEX input   " +
                  ' '.join([str(hex(int(x))) for x in X]))
            print("Round [" + str(ROUNDS - 0.5) + "] HEX sub-key " +
                  ' '.join([str(hex(int(k, 2))) for k in K[ROUNDS - 1]]))
            print("Round [" + str(ROUNDS - 0.5) + "] HEX output  " +
                  ' '.join([str(hex(int(x)))
                            for x in result]) + "\n---------------")
            print("Final Cipher/Decipher: " + cipher + "\n---------------")

        return cipher  # Hex string

    def encrypt(self, plain_text=''):
        if self.log:
            print("-------ENCRYPTING [" + plain_text + "]-------")
        plain_text = get_pt_block(plain_text)
        return self.calculate_cipher(self.enc_sub_keys, plain_text)

    def decrypt(self, cipher_text=''):
        if self.log:
            print("-------DECRYPTING [" + cipher_text + "]-------")
        cipher_text = get_cipher_block(cipher_text)
        res = self.calculate_cipher(self.dec_sub_keys, cipher_text)
        res = ''.join('0' * (16 - len(res))) + res
        return ''.join(
            [chr(int(''.join(c), 16)) for c in zip(res[0::2], res[1::2])])