repo_description: ⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡
repo_topics: artificial-intelligence cipher cpp cryptography ctf ctf-tools cyberchef-magic decryption deep-neural-network encodings encryptions hacking hacktoberfest hashes natural-language-processing pentesting python
code: //! Decodes a base58 flickr string
  //! Performs error handling and returns a string
  //! Call base58_flickr_decoder.crack to use. It returns option<String> and check with
  //! `result.is_some()` to see if it returned okay.
  
  use crate::checkers::CheckerTypes;
  use crate::decoders::interface::check_string_success;
  
  use super::crack_results::CrackResult;
  use super::interface::Crack;
  use super::interface::Decoder;
  
  use log::{debug, info, trace};
  
  /// The Base58_flickr decoder, call:
  /// `let base58_flickr_decoder = Decoder::<Base58FlickrDecoder>::new()` to create a new instance
  /// And then call:
  /// `result = base58_flickr_decoder.crack(input)` to decode a base58_flickr string
  /// The struct generated by new() comes from interface.rs
  /// ```
  /// use ciphey::decoders::base58_flickr_decoder::{Base58FlickrDecoder};
  /// use ciphey::decoders::interface::{Crack, Decoder};
  /// use ciphey::checkers::{athena::Athena, CheckerTypes, checker_type::{Check, Checker}};
  ///
  /// let decode_base58_flickr = Decoder::<Base58FlickrDecoder>::new();
  /// let athena_checker = Checker::<Athena>::new();
  /// let checker = CheckerTypes::CheckAthena(athena_checker);
  ///
  /// let result = decode_base58_flickr.crack("rTu1dk6cWsRYjYu", &checker).unencrypted_text;
  /// assert!(result.is_some());
  /// assert_eq!(result.unwrap()[0], "hello world");
  /// ```
  pub struct Base58FlickrDecoder;
  
  impl Crack for Decoder<Base58FlickrDecoder> {
      fn new() -> Decoder<Base58FlickrDecoder> {
          Decoder {
              name: "Base58 Flickr",
              description: "Base58 is a group of binary-to-text encoding schemes that represent binary data (more specifically, a sequence of 8-bit bytes) in an ASCII string format by translating the data into a radix-32 representation.",
              link: "https://en.wikipedia.org/wiki/Base58",
              tags: vec!["base58_flickr", "base58", "flickr", "decoder", "base"],
              popularity: 0.4,
              phantom: std::marker::PhantomData,
          }
      }
  
      /// This function does the actual decoding
      /// It returns an Option<string> if it was successful
      /// Else the Option returns nothing and the error is logged in Trace
      fn crack(&self, text: &str, checker: &CheckerTypes) -> CrackResult {
          trace!("Trying Base58_flickr with text {:?}", text);
          let decoded_text = decode_base58_flickr_no_error_handling(text);
          let mut results = CrackResult::new(self, text.to_string());
  
          if decoded_text.is_none() {
              debug!("Failed to decode base58_flickr because Base58FlickrDecoder::decode_base58_flickr_no_error_handling returned None");
              return results;
          }
  
          let decoded_text = decoded_text.unwrap();
          if !check_string_success(&decoded_text, text) {
              info!(
                  "Failed to decode base58_flickr because check_string_success returned false on string {}",
                  decoded_text
              );
              return results;
          }
  
          let checker_result = checker.check(&decoded_text);
          results.unencrypted_text = Some(vec![decoded_text]);
  
          results.update_checker(&checker_result);
  
          results
      }
      /// Gets all tags for this decoder
      fn get_tags(&self) -> &Vec<&str> {
          &self.tags
      }
      /// Gets the name for the current decoder
      fn get_name(&self) -> &str {
          self.name
      }
      /// Gets the description for the current decoder
      fn get_description(&self) -> &str {
          self.description
      }
      /// Gets the link for the current decoder
      fn get_link(&self) -> &str {
          self.link
      }
  }
  
  /// helper function
  fn decode_base58_flickr_no_error_handling(text: &str) -> Option<String> {
      // Runs the code to decode base58_flickr
      // Doesn't perform error handling, call from_base58_flickr
      if let Ok(decoded_text) = bs58::decode(text)
          .with_alphabet(bs58::Alphabet::FLICKR)
          .into_vec()
      {
          return Some(String::from_utf8_lossy(&decoded_text).to_string());
      }
      None
  }
  
  #[cfg(test)]
  mod tests {
      use super::Base58FlickrDecoder;
      use crate::{
          checkers::{
              athena::Athena,
              checker_type::{Check, Checker},
              CheckerTypes,
          },
          decoders::interface::{Crack, Decoder},
      };
  
      // helper for tests
      fn get_athena_checker() -> CheckerTypes {
          let athena_checker = Checker::<Athena>::new();
          CheckerTypes::CheckAthena(athena_checker)
      }
  
      #[test]
      fn successful_decoding() {
          let base58_flickr_decoder = Decoder::<Base58FlickrDecoder>::new();
          let result = base58_flickr_decoder.crack("rTu1dk6cWsRYjYu", &get_athena_checker());
          assert_eq!(result.unencrypted_text.unwrap()[0], "hello world");
      }
  
      #[test]
      fn base58_flickr_decode_empty_string() {
          // Base58_flickr returns an empty string, this is a valid base58_flickr string
          // but returns False on check_string_success
          let base58_flickr_decoder = Decoder::<Base58FlickrDecoder>::new();
          let result = base58_flickr_decoder
              .crack("", &get_athena_checker())
              .unencrypted_text;
          assert!(result.is_none());
      }
  
      #[test]
      fn base58_flickr_decode_handles_panics() {
          let base58_flickr_decoder = Decoder::<Base58FlickrDecoder>::new();
          let result = base58_flickr_decoder
              .crack(
                  "hello my name is panicky mc panic face!",
                  &get_athena_checker(),
              )
              .unencrypted_text;
          assert!(result.is_none());
      }
  
      #[test]
      fn base58_flickr_handle_panic_if_empty_string() {
          let base58_flickr_decoder = Decoder::<Base58FlickrDecoder>::new();
          let result = base58_flickr_decoder
              .crack("", &get_athena_checker())
              .unencrypted_text;
          assert!(result.is_none());
      }
  
      #[test]
      fn base58_flickr_work_if_string_not_base58_flickr() {
          // You can base58_flickr decode a string that is not base58_flickr
          // This string decodes to:
          // ```.ée¢
          // (uÖ²```
          // https://gchq.github.io/CyberChef/#recipe=From_Base58('A-Za-z0-9%2B/%3D',true)&input=aGVsbG8gZ29vZCBkYXkh
          let base58_flickr_decoder = Decoder::<Base58FlickrDecoder>::new();
          let result = base58_flickr_decoder
              .crack("hello good day!", &get_athena_checker())
              .unencrypted_text;
          assert!(result.is_none());
      }
  
      #[test]
      fn base58_flickr_handle_panic_if_emoji() {
          let base58_flickr_decoder = Decoder::<Base58FlickrDecoder>::new();
          let result = base58_flickr_decoder
              .crack("😂", &get_athena_checker())
              .unencrypted_text;
          assert!(result.is_none());
      }
  }
  