Example #1
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        UUEncode (Unix to Unix Encoding) is a symmetric encryption
        based on conversion of binary data (split into 6-bit blocks) into ASCII characters.

        This function decodes the input string 'ctext' if it has been encoded using 'uuencoder'
        It will return None otherwise
        """
        logger.trace("Attempting UUencode")
        result = ""
        try:
            # UUencoded messages may begin with prefix "begin" and end with suffix "end"
            # In that case, we use the codecs module in Python
            ctext_strip = ctext.strip()
            if ctext_strip.startswith("begin") and ctext_strip.endswith("end"):
                result = decode(bytes(ctext, "utf-8"), "uu").decode()
            else:
                # If there isn't a "being" prefix and "end" suffix, we use the binascii module instead
                # It is possible that the ctext has multiple lines, so convert each line and append
                ctext_split = list(filter(None, ctext.splitlines()))
                for i in range(0, len(ctext_split)):
                    result += a2b_uu(ctext_split[i]).decode("utf-8")
            logger.debug(f"UUencode successful, returning '{result}'")
            return result
        except Exception:
            logger.trace("Failed to decode UUencode")
            return None
Example #2
0
    def check(self, ctext: T) -> Optional[str]:
        logging.debug("Trying PyWhat checker")
        returned_regexes = self.id.identify(ctext, api=True)
        if len(returned_regexes["Regexes"]) > 0:

            matched_regex = returned_regexes["Regexes"][0]["Regex Pattern"]

            ret = f'The plaintext is a [yellow]{matched_regex["Name"]}[/yellow]'
            human = f'\nI think the plaintext is a [yellow]{matched_regex["Name"]}[/yellow]'

            if "Description" in matched_regex and matched_regex["Description"]:
                s = matched_regex['Description']
                # lowercases first letter so it doesn't look weird
                s = f", which is {s[0].lower() + s[1:]}\n"
                ret += s
                human += s

            # if URL is attached, include that too.
            if "URL" in matched_regex:
                link = matched_regex['URL'] + ctext.replace(' ', '')
                ret += f"\nClick here to view in browser [#CAE4F1][link={link}]{link}[/link][/#CAE4F1]\n"

            # If greppable mode is on, don't print this
            if self.config.verbosity > 0:
                # Print with full stop
                console.print(human)
            return ret
        return None
Example #3
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        Takes an encoded string and attempts to decode it according to the Atbash cipher.

            The Atbash cipher is a very simple substitution cipher without a key.
            It operates by replacing every letter in the input by its 'counterpoint'
            in the alphabet. Example: A -> Z, B -> Y, ... , M -> N and vice versa.
        """

        result = ""
        letters = list("abcdefghijklmnopqrstuvwxyz")
        atbash_dict = {letters[i]: letters[::-1][i] for i in range(26)}

        # Ensure that ciphertext is a string
        if type(ctext) == str:
            # Normalize the string to all-lowercase letters
            ctext = ctext.lower()
        else:
            return None

        for letter in ctext:
            if letter in atbash_dict.keys():
                # Match every letter of the input to its atbash counterpoint
                result += atbash_dict[letter]
            else:
                # If the current character is not in the defined alphabet,
                # just accept it as-is (useful for numbers, punctuation,...)
                result += letter
        return result
Example #4
0
 def decode(self, ctext: T) -> Optional[U]:
     result = ""
     switch_to_digit_map = 0
     if re.search("^[01]{5}$", ctext.split()[0]):
         for i in ctext.split():
             if i == "11011":
                 switch_to_digit_map = 1
             if i == "11111":
                 switch_to_digit_map = 0
             if switch_to_digit_map == 1:
                 result += self.BAUDOT_DICT["+" + i]
             if switch_to_digit_map == 0:
                 result += self.BAUDOT_DICT[i]
         return result
     else:
         return None
Example #5
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        Performs Octal decoding
        """
        str_converted = []
        octal_seq = ctext.split(" ")
        if len(octal_seq) == 1:
            # Concatted octal must be formed of octal triplets
            if len(ctext) % 3 != 0:
                return None
            octal_seq = [ctext[i : i + 3] for i in range(0, len(ctext), 3)]
            logger.trace(f"Trying chunked octal {octal_seq}")
        try:
            for octal_char in octal_seq:
                if len(octal_char) > 3:
                    logger.trace("Octal subseq too long")
                    return None
                n = int(octal_char, 8)
                if (
                    n < 0
                ):  # n cannot be greater than 255, as we checked that with the earlier length check
                    logger.trace(f"Non octal char {octal_char}")
                    return None
                str_converted.append(n)

            return bytes(str_converted)
        # Catch bad octal chars
        except ValueError:
            return None
Example #6
0
    def decode(self, ctext: T) -> Optional[U]:
        try:
            ctext = re.sub(r"[^\S \n]", " ", ctext, flags=re.UNICODE)
            ctext = ctext.replace("\n", " ")

            existing_split = self.try_split(ctext.split(" "))
            if existing_split is not None:
                return existing_split

            # Now we try our own grouping

            # Remove final bit of whitespace
            ctext = ctext.replace(" ", "")
            # Split into bytes, and test
            return self.try_split([ctext[i : i + 8] for i in range(0, len(ctext), 8)])
        # Catch bad octal chars
        except ValueError:
            return None
Example #7
0
    def decode(self, ctext: T) -> Optional[U]:
        try:
            output = ""
            combinations = ctext.split(" ")
            for fragment in combinations:
                output += self.TABLE.get(fragment)
            return output

        except Exception as e:
            return None
Example #8
0
    def decode(self, ctext: T) -> Optional[U]:
        logger.trace("Attempting Morse code decoder")

        char_boundary = word_boundary = None

        char_boundary = word_boundary = None
        char_priority = word_priority = 0
        # Custom loop allows early break
        for i in ctext:
            i_priority = self.BOUNDARIES.get(i)
            if i_priority is None:
                if i in self.ALLOWED:
                    continue
                logger.trace(f"Non-morse char '{i}' found")
                return None

            if i_priority <= char_priority or i == char_boundary or i == word_boundary:
                continue
            # Default to having a char boundary over a word boundary
            if (i_priority > word_priority and word_boundary is None
                    and char_boundary is not None):
                word_priority = i_priority
                word_boundary = i
                continue
            char_priority = i_priority
            char_boundary = i

        logger.trace(
            f"Char boundary is unicode {ord(char_boundary)}, and word boundary is unicode {ord(word_boundary) if word_boundary is not None else None}"
        )

        result = ""

        for word in ctext.split(word_boundary) if word_boundary else [ctext]:
            logger.trace(f"Attempting to decode word {word}")
            for char in word.split(char_boundary):
                char = char.translate(self.PURGE)
                if len(char) == 0:
                    continue
                try:
                    m = self.MORSE_CODE_DICT_INV[char]
                except KeyError:
                    logger.trace(f"Invalid codeword '{char}' found")
                    return None
                result = result + m
            # after every word add a space
            result = result + " "
        if len(result) == 0:
            logger.trace("Morse code failed to match")
            return None
        # Remove trailing space
        result = result[:-1]
        logger.debug(f"Morse code successful, returning {result}")
        return result.strip().upper()
Example #9
0
 def decode(self, ctext: T) -> Optional[U]:
     """
     Performs Tap code decoding
     """
     try:
         result = ""
         combinations = ctext.split(" ")
         for fragment in combinations:
             result += self.TABLE.get(fragment)
         return result
     except Exception:
         return None
Example #10
0
    def check(self, text: T) -> Optional[str]:
        logger.trace(f"Trying json checker")

        # https://github.com/Ciphey/Ciphey/issues/389
        if text.isdigit():
            return None

        try:
            json.loads(text)
            return ""
        except ValueError:
            return None
Example #11
0
    def decode(self, ctext: T) -> Optional[U]:
        """Write the code that decodes here
        ctext -> the input to the function
        returns string
    """

        ret = ""
        switch_to_digit_map = 0
        if type(ctext) == str:
            if re.search("^[01]{5}$", ctext.split()[0]):
                for i in ctext.split():
                    if i == "11011":
                        switch_to_digit_map = 1
                    if i == "11111":
                        switch_to_digit_map = 0
                    if switch_to_digit_map == 1:
                        ret += self.BAUDOT_DICT["+" + i]
                    if switch_to_digit_map == 0:
                        ret += self.BAUDOT_DICT[i]
                return ret
        else:
            return None
Example #12
0
 def decode(self, ctext: T) -> Optional[U]:
     """
     Performs UTF-8 decoding
     """
     logger.trace("Attempting UTF-8 decoder")
     result = ""
     try:
         result = ctext.decode("utf-8")
         if result != ctext:
             logger.debug(f"UTF-8 successful, returning '{result}'")
             return result
         else:
             return None
     except Exception:
         return None
Example #13
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        Performs DNA decoding
        """
        logger.trace("Attempting DNA decoder")
        ctext_decoded = ""
        ctext = re.sub(r"[,;:\-\s]", "", ctext)
        ctext = " ".join(ctext[i:i + 3] for i in range(0, len(ctext), 3))
        ctext_split = ctext.split(" ")
        dna_keys = self.DNA_DICT.keys()

        for i in ctext_split:
            if i in dna_keys:
                ctext_decoded += self.DNA_DICT[i]
            else:
                return None
        logger.debug(f"DNA successful, returning '{ctext_decoded}'")
        return ctext_decoded
Example #14
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        Performs DTMF decoding
        """
        logging.debug("Attempting DTMF decoder")
        ctext_decoded = ""
        ctext = re.sub(r"[,;:\-\/\s]", "", ctext)
        ctext = " ".join(ctext[i:i + 7] for i in range(0, len(ctext), 7))
        ctext_split = ctext.split(" ")
        dtmf_keys = self.DTMF_DICT.keys()

        for i in ctext_split:
            if i in dtmf_keys:
                ctext_decoded += self.DTMF_DICT[i]
            else:
                return None
        logging.info(f"DTMF successful, returning '{ctext_decoded}'")
        return ctext_decoded
Example #15
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        Takes a string written in the 'Standard Galactic Alphabet' 
        (aka Minecraft Enchanting Table Symbols) and translates it to ASCII text.
        """
        logger.trace("Attempting Standard Galactic Alphabet Decoder")

        # To avoid complications, only move forward with the decoding if we can
        # reasonably assume that the input string is written in the galactic alphabet
        galactic_matches = 0
        for symbol in self.GALACTIC_DICT.keys():
            # These symbols are assumed to be frequent enough in regular
            # text to be skipped when counting the matches. All others are counted.
            if symbol in ctext and symbol not in ["!", "|"]:
                galactic_matches += 1
            else:
                continue
        if galactic_matches == 0:
            logger.trace(
                "No matching galactic alphabet letters found. Skipping galactic decoder..."
            )
            return None
        logger.trace(f"{galactic_matches} galactic alphabet letters found. ")

        result = ""
        ctext = (ctext.replace("||",
                               "|").replace("/", "").replace("¡", "").replace(
                                   " ̣ ", "").replace(" ̇", " x"))
        logger.trace(f"Modified string is {ctext}")
        # Take out the problematic characters consisting of multiple symbols
        for letter in ctext:
            if letter in self.GALACTIC_DICT.keys():
                # Match every letter of the input to its galactic counterpoint
                result += self.GALACTIC_DICT[letter]
            else:
                # If the current character is not in the defined alphabet,
                # just accept it as-is (useful for numbers, punctuation,...)
                result += letter

        result = result.replace("x ", "x")
        # Remove the trailing space (appearing as a leading space)
        # from the x that results from the diacritic replacement
        logger.trace(f"Decoded string is {result}")
        return result
Example #16
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        Takes an encoded string and attempts to decode it according to the Atbash cipher.

            The Atbash cipher is a very simple substitution cipher without a key.
            It operates by replacing every letter in the input by its 'counterpoint'
            in the alphabet. Example: A -> Z, B -> Y, ... , M -> N and vice versa.
        """

        result = ""
        atbash_dict = {self.ALPHABET[i]: self.ALPHABET[::-1][i] for i in range(26)}

        for letter in ctext.lower():
            if letter in atbash_dict.keys():
                # Match every letter of the input to its atbash counterpoint
                result += atbash_dict[letter]
            else:
                # If the current character is not in the defined alphabet,
                # just accept it as-is (useful for numbers, punctuation,...)
                result += letter
        return fix_case(result, ctext)
Example #17
0
    def decode(self, ctext: T) -> Optional[U]:
        """
        Performs Braille decoding
        """
        logger.trace("Attempting Braille")
        ctext_decoded = ""
        braille_matches = 0
        for symbol in self.BRAILLE_DICT_INV.values():
            if symbol in ctext:
                braille_matches += 1
            else:
                continue
        if braille_matches == 0:
            logger.trace("Failed to decode Braille due to invalid characters")
            return None

        for pattern, value in self.BRAILLE_DICT.items():
            ctext = re.sub(pattern, value, ctext)

        wordArr = []
        for word in ctext.split(" "):
            # If two commas are in front of a word, uppercase the word and remove the comma
            if word[:2].find(",,") != -1:
                wordArr.append(word.replace(",,", "").upper())
            else:
                wordArr.append(word)

        result = []
        for word in wordArr:
            # If one comma is in front of a word, capitalize the word and remove the comma
            if word[0].find(",") != -1:
                result.append(word.replace(",", "").capitalize())
            else:
                result.append(word)
        ctext_decoded = " ".join(result)
        logger.debug(f"Braille successful, returning '{ctext_decoded}'")
        return ctext_decoded
Example #18
0
 def check(self, ctext: T) -> Optional[str]:
     logging.debug("Trying Quadgrams checker")
     # Capitalize and remove everything that's not a letter
     ctext = re.sub("[^A-Z]", "", ctext.upper())
     quadgrams = self.QUADGRAMS_DICT
     quadgrams_sum = sum(quadgrams.values())
     score = 0
     for key in quadgrams.keys():
         quadgrams[key] = float(quadgrams[key]) / quadgrams_sum
     floor = log10(0.01 / quadgrams_sum)
     for i in range(len(ctext) - 4 + 1):
         # Get all quadgrams from ctext and check if they're in the dict
         # If yes then add the score of those quadgrams to the total score
         if ctext[i:i + 4] in quadgrams:
             score += quadgrams[ctext[i:i + 4]]
         else:
             score += floor
     if len(ctext) > 0:
         score = score / len(ctext)
     logging.info(f"Quadgrams is {score}")
     # The default threshold was found to work the best from lots of testing
     if score > self.threshold:
         return ""
     return None
Example #19
0
 def decode(self, ctext: T) -> Optional[U]:
     for src, dst in self.translate.items():
         ctext = ctext.replace(src, dst)
     return ctext