Esempio n. 1
0
    def decode(self, ciphertext):
        try:
            if self.cipher_mode == AES.MODE_EAX:
                cipher = AES.new(key=self.key,
                                 mode=self.cipher_mode,
                                 nonce=self.nonce)
                cipherbytes = b64decode(ciphertext.encode(self.text_encoding))
                data = cipher.decrypt(cipherbytes)
            elif self.cipher_mode == AES.MODE_CBC:
                cipher = AES.new(key=self.key,
                                 mode=self.cipher_mode,
                                 iv=self.nonce)
                cipherbytes = b64decode(ciphertext.encode(self.text_encoding))
                data = cipher.decrypt(cipherbytes)
                Log.debugdebug(
                    str(self.__class__) + ' ' +
                    str(getframeinfo(currentframe()).lineno) +
                    ': Decrypted data length = ' + str(len(data)) +
                    ', modulo 16 = ' + str(len(data) % 128 / 8))
                # Remove last x bytes encoded in the padded bytes
                data = data[:-data[-1]]
            else:
                raise Exception(
                    str(self.__class__) + ' ' +
                    str(getframeinfo(currentframe()).lineno) +
                    ': Unsupported mode "' + str(self.cipher_mode) + '".')

            return str(data, encoding=STR_ENCODING)
        except Exception as ex:
            errmsg = str(__name__) + ' ' + str(getframeinfo(currentframe()).lineno) \
                    + ': Error decoding data "' + str(ciphertext) + '" using AES ". Exception: ' + str(ex)
            Log.error(errmsg)
            raise Exception(errmsg)
Esempio n. 2
0
    def hash_compression(
            self,
            s,
            # By default we return the original hash
            desired_byte_length = 32
    ):
        if desired_byte_length % 4 != 0:
            raise Exception(
                str(self.__class__) + ' ' + str(getframeinfo(currentframe()).lineno)
                + ': Desired byte length must be 0 modulo-4, given = ' + str(desired_byte_length)
            )

        m = hashlib.sha256()
        m.update(bytes(s, encoding=Obfuscate.STRING_ENCODING))
        # This will return a bytes list of length 32
        h = m.digest()
        if len(h) % 4 != 0:
            raise Exception(
                str(__name__) + ' ' + str(getframeinfo(currentframe()).lineno)
                + ': Hash bytes length must be 0 modulo-4, got = ' + str(h)
            )

        # We compress to 8 bytes from the 32 bytes
        # The original SHA-256 appends 8 parts concatenated together, we break into 4 parts and xor them

        # 4 blocks
        n_blocks = int( len(h) / desired_byte_length )
        # 8 bytes block length
        block_len = int( len(h) / n_blocks )
        Log.debugdebug(
            str(self.__class__) + ' ' + str(getframeinfo(currentframe()).lineno)
            + ': Number of blocks = ' + str(n_blocks) + ', block length = ' + str(block_len)
        )

        # First block
        bytes_xor = h[0:block_len]
        for i in range(1, n_blocks, 1):
            idx_start = i * block_len
            idx_end = (i+1) * block_len
            cur_block = h[idx_start:idx_end]
            if len(bytes_xor) != len(cur_block):
                raise Exception(
                    str(self.__class__) + ' ' + str(getframeinfo(currentframe()).lineno)
                    + ': Different block lengths "' + str(bytes_xor)
                    + '", and "' + str(cur_block) + '"'
                )
            bytes_xor = self.xor_bytes(
                b1 = bytes_xor,
                b2 = cur_block
            )

        return bytes_xor
Esempio n. 3
0
 def encode(
         self,
         # bytes format
         data):
     try:
         if self.cipher_mode == AES.MODE_EAX:
             cipher = AES.new(key=self.key,
                              mode=self.cipher_mode,
                              nonce=self.nonce)
             cipherbytes, tag = cipher.encrypt_and_digest(data)
             return AES_Encrypt.EncryptRetClass(
                 cipher_mode=self.cipher_mode_str,
                 ciphertext_b64=b64encode(cipherbytes).decode(
                     self.text_encoding),
                 plaintext_b64=None,
                 tag_b64=b64encode(tag).decode(self.text_encoding),
                 nonce_b64=b64encode(self.nonce).decode(self.text_encoding))
         elif self.cipher_mode == AES.MODE_CBC:
             # 1-16, make sure not 0, other wise last byte will not be block length
             length = AES_Encrypt.DEFAULT_BLOCK_SIZE_AES_CBC - (
                 len(data) % AES_Encrypt.DEFAULT_BLOCK_SIZE_AES_CBC)
             # Pad data with the original length, so when we decrypt we can just take data[-1]
             # as length of data block
             data += bytes(chr(length), encoding=STR_ENCODING) * length
             Log.debugdebug(
                 str(self.__class__) + ' ' +
                 str(getframeinfo(currentframe()).lineno) +
                 ': Padded length = ' + str(length))
             cipher = AES.new(key=self.key,
                              mode=self.cipher_mode,
                              iv=self.nonce)
             cipherbytes = cipher.encrypt(data)
             return AES_Encrypt.EncryptRetClass(
                 cipher_mode=self.cipher_mode_str,
                 ciphertext_b64=b64encode(cipherbytes).decode(
                     self.text_encoding),
                 plaintext_b64=None,
                 tag_b64=None,
                 nonce_b64=b64encode(self.nonce).decode(self.text_encoding))
         else:
             raise Exception(
                 str(self.__class__) + ' ' +
                 str(getframeinfo(currentframe()).lineno) +
                 ': Unsupported mode "' + str(self.cipher_mode) + '".')
     except Exception as ex:
         errmsg = str(__name__) + ' ' + str(getframeinfo(currentframe()).lineno) \
                 + ': Error encoding data "' + str(data) + '" using AES ". Exception: ' + str(ex)
         Log.error(errmsg)
         raise Exception(errmsg)
Esempio n. 4
0
    def convert_ascii_string_to_other_alphabet(
        ascii_char_string,
        # Default to CJK Unicode Block
        unicode_range=BLOCK_CHINESE,
        # If the characters come from a hexdigest from a hash, we can compress 4 times,
        # otherwise for a random ascii string, we can only compress 2 characters to 1 chinese.
        group_n_char=2):
        uni_len = unicode_range[1] - unicode_range[0] + 1

        r = len(ascii_char_string) % 4
        if r != 0:
            # Append 0's
            ascii_char_string = ascii_char_string + '0' * (4 - r)
        # raise Exception('Hash length ' + str(len(hash_hex_string))
        #                 + ' for "' + str(hash_hex_string) + '" not 0 modulo-4')

        hash_zh = ''

        len_block = int(len(ascii_char_string) / group_n_char)
        for i in range(0, len_block, 1):
            idx_start = group_n_char * i
            idx_end = idx_start + group_n_char
            s = ascii_char_string[idx_start:idx_end]

            # Convert to Chinese, Korean, etc
            if group_n_char == 2:
                ord_arr = np.array([ord(x) for x in s])
                val = ord_arr * np.array(
                    [2**(8 * (x - 1)) for x in range(len(ord_arr), 0, -1)])
                val = np.sum(val)
                Log.debug('Index start=' + str(idx_start) + ', end=' +
                          str(idx_end) + ', s=' + str(s) + ', ordinal=' +
                          str(ord_arr) + ', val=' + str(hex(val)))
                cjk_unicode = (val % uni_len) + unicode_range[0]
                hash_zh += chr(cjk_unicode)
            elif group_n_char == 4:
                Log.debug('Index start=' + str(idx_start) + ', end=' +
                          str(idx_end) + ', s=' + str(s))
                n = int('0x' + str(s), 16)
                cjk_unicode = (n % uni_len) + unicode_range[0]
                hash_zh += chr(cjk_unicode)
                Log.debugdebug('From ' + str(idx_start) + ': ' + str(s) +
                               ', n=' + str(n) + ', char=' +
                               str(chr(cjk_unicode)))

        return hash_zh
Esempio n. 5
0
    def xor_string(
            self,
            s1,
            s2
    ):
        Log.debug(
            str(__name__) + ' ' + str(getframeinfo(currentframe()).lineno)
            + ': XOR between "' + str(s1) + '" and "' + str(s2) + '".'
        )

        len_s1 = len(s1)
        len_s2 = len(s2)
        len_max = max(len(s1), len(s2))

        # Append to the shorter one, in a repeat manner
        for i in range(len(s1), len_max, 1):
            s1 += s1[(i-len_s1)]
        for i in range(len(s2), len_max, 1):
            s2 += s2[(i-len_s2)]

        Log.debug(
            str(self.__class__) + ' ' + str(getframeinfo(currentframe()).lineno)
            + ': After appending, XOR between "' + str(s1) + '" and "' + str(s2) + '".'
        )

        Log.debugdebug(
            str(self.__class__) + ' ' + str(getframeinfo(currentframe()).lineno)
            + ': s1 "' + str(s1) + '", s2 "' + str(s2) + '"'
        )

        b1 = bytes(s1, encoding=Obfuscate.STRING_ENCODING)
        b2 = bytes(s2, encoding=Obfuscate.STRING_ENCODING)

        bytes_xor = self.xor_bytes(
            b1 = b1,
            b2 = b2
        )

        return bytes_xor
Esempio n. 6
0
    def xor_bytes(
            self,
            b1,
            b2
    ):
        t12 = zip(b1,b2)

        res_xor = []
        for x in t12:
            byte_xor = x[0] ^ x[1]
            Log.debugdebug(
                str(self.__class__) + ' ' + str(getframeinfo(currentframe()).lineno)
                + 'XOR "' + str(hex(x[0])) + '" and "' + str(hex(x[1])) + '" = ' + str(hex(byte_xor))
            )
            res_xor.append(byte_xor)

        Log.debug(
            str(self.__class__) + ' ' + str(getframeinfo(currentframe()).lineno)
            + ': XOR between "' + str(self.hexdigest(b1))
            + '" and "' + str(self.hexdigest(b2))
            + '" = "' + str(self.hexdigest(res_xor)) + '"'
        )

        return res_xor