Example #1
0
    def attemptCrack(self, ctext: str) -> List[CrackResult]:
        """
        Brute forces all the possible combinations of a and b to attempt to crack the cipher.
        """
        logger.trace("Attempting affine")
        candidates = []

        # a and b are coprime if gcd(a,b) is 1.
        possible_a = [
            a for a in range(1, self.alphabet_length)
            if mathsHelper.gcd(a, self.alphabet_length) == 1
        ]
        logger.debug(
            f"Trying Affine Cracker with {len(possible_a)} a-values and {self.alphabet_length} b-values"
        )

        for a in possible_a:
            a_inv = mathsHelper.mod_inv(a, self.alphabet_length)
            # If there is no inverse, we cannot decrypt the text
            if a_inv is None:
                continue
            for b in range(self.alphabet_length):
                # Pass in lowered text. This means that we expect alphabets to not contain both 'a' and 'A'.
                translated = self.decrypt(ctext.lower(), a_inv, b,
                                          self.alphabet_length)

                candidate_probability = self.plaintext_probability(translated)
                if candidate_probability > self.plaintext_prob_threshold:
                    candidates.append(
                        CrackResult(value=fix_case(translated, ctext),
                                    key_info=f"a={a}, b={b}"))
        logger.debug(f"Affine Cipher returned {len(candidates)} candidates")
        return candidates
Example #2
0
 def crackOne(self, ctext: str, analysis: cipheycore.windowed_analysis_res,
              real_ctext: str) -> List[CrackResult]:
     possible_keys = cipheycore.vigenere_crack(analysis, self.expected,
                                               self.group, self.p_value)
     logger.trace(
         f"Vigenere crack got keys: {[[i for i in candidate.key] for candidate in possible_keys]}"
     )
     # if len(possible_keys) and possible_keys[0].p_value < 0.9999999:
     #     raise 0
     return [
         CrackResult(
             value=fix_case(
                 cipheycore.vigenere_decrypt(ctext, candidate.key,
                                             self.group), real_ctext),
             key_info="".join([self.group[i] for i in candidate.key]),
         ) for candidate in possible_keys[:min(len(possible_keys), 10)]
     ]
Example #3
0
    def attemptCrack(self, ctext: str) -> List[CrackResult]:
        logging.info(f"Trying caesar cipher on {ctext}")
        # Convert it to lower case
        #
        # TODO: handle different alphabets
        if self.lower:
            message = ctext.lower()
        else:
            message = ctext

        logging.debug("Beginning cipheycore simple analysis")

        # Hand it off to the core
        analysis = self.cache.get_or_update(
            ctext,
            "cipheycore::simple_analysis",
            lambda: cipheycore.analyse_string(ctext),
        )
        logging.debug("Beginning cipheycore::caesar")
        possible_keys = cipheycore.caesar_crack(analysis, self.expected,
                                                self.group, self.p_value)

        n_candidates = len(possible_keys)
        logging.info(f"Caesar returned {n_candidates} candidates")

        if n_candidates == 0:
            logging.debug("Filtering for better results")
            analysis = cipheycore.analyse_string(ctext, self.group)
            possible_keys = cipheycore.caesar_crack(analysis, self.expected,
                                                    self.group, self.p_value)

        candidates = []

        for candidate in possible_keys:
            logging.debug(
                f"Candidate {candidate.key} has prob {candidate.p_value}")
            translated = cipheycore.caesar_decrypt(message, candidate.key,
                                                   self.group)
            candidates.append(
                CrackResult(value=fix_case(translated, ctext),
                            key_info=candidate.key))

        return candidates
Example #4
0
 def crackOne(
     self, ctext: str, analysis: cipheycore.windowed_analysis_res, real_ctext: str
 ) -> List[CrackResult]:
     possible_keys = cipheycore.vigenere_crack(
         analysis, self.expected, self.group, self.p_value
     )
     if len(possible_keys) > self.clamp:
         possible_keys = possible_keys[:self.clamp]
     logger.trace(
         f"Vigenere crack got keys: {[[i for i in candidate.key] for candidate in possible_keys]}"
     )
     return [
         CrackResult(
             value=fix_case(cipheycore.vigenere_decrypt(ctext, candidate.key, self.group), real_ctext),
             key_info="".join([self.group[i] for i in candidate.key]),
             misc_info=f"p-value was {candidate.p_value}"
         )
         for candidate in possible_keys[: min(len(possible_keys), 10)]
     ]
Example #5
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)