UNCIDOE string verschlüsseln



  • Hi zusammen,
    ich bin dabei einen string zu verschlüsseln.
    Da der String aus UNICODE zeichen bestehen kann, habe ich alle Zeichen entsprechend definiert:

    Nun möchte ich meinen String codieren bzw. decodieren, dafür habe ich einen Code im Netz gefunden:

    Ich rufe die Kodierung wie folgt auf:

    #ifdef UNICODE
           #define cout wcout
           #define tstring wstring
           #define _TUCHAR wchar_t
    #else
           #define cout cout
           #define tstring string
           #define _TUCHAR unsigned char 
    #endif
    
    const std::tstring s = klartext;
    std::tstring encoded = base64_encode(reinterpret_cast<const _TUCHAR*>(s.c_str()), s.length());
    

    base64.cpp

    static const std::tstring base64_chars = 
                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                 "abcdefghijklmnopqrstuvwxyz"
                 "0123456789+/";
    
    static inline bool is_base64(_TUCHAR c) {
      return (isalnum(c) || (c == '+') || (c == '/'));
    }
    
    std::tstring base64_encode(_TUCHAR const* bytes_to_encode, unsigned int in_len) {
      std::tstring ret;
      int i = 0;
      int j = 0;
      _TUCHAR char_array_3[3];
      _TUCHAR char_array_4[4];
    
      while (in_len--) {
        char_array_3[i++] = *(bytes_to_encode++);
        if (i == 3) {
          char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
          char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
          char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
          char_array_4[3] = char_array_3[2] & 0x3f;
    
          for(i = 0; (i <4) ; i++)
            ret += base64_chars[char_array_4[i]];
          i = 0;
        }
      }
    
      if (i)
      {
        for(j = i; j < 3; j++)
          char_array_3[j] = '\0';
    
        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;
    
        for (j = 0; (j < i + 1); j++)
          ret += base64_chars[char_array_4[j]];
    
        while((i++ < 3))
          ret += '=';
    
      }
    
      return ret;
    
    }
    
    std::tstring base64_decode(std::tstring const& encoded_string) {
      int in_len = encoded_string.size();
      int i = 0;
      int j = 0;
      int in_ = 0;
      _TUCHAR char_array_4[4], char_array_3[3];
      std::tstring ret;
    
      while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
        char_array_4[i++] = encoded_string[in_]; in_++;
        if (i ==4) {
          for (i = 0; i <4; i++){
            char_array_4[i] = base64_chars.find(char_array_4[i]);
          }
    
          char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
          char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
          char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
    
          for (i = 0; (i < 3); i++)
            ret += char_array_3[i];
          i = 0;
        }
      }
    
      if (i) {
        for (j = i; j <4; j++)
          char_array_4[j] = 0;
    
        for (j = 0; j <4; j++){
            char_array_4[j] = base64_chars.find(char_array_4[j]);
        }
    
        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
    
        for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
      }
    
      return ret;
    }
    

    So,
    das alles funktioniert ja wunderbar (bei meinem lokalen System) aber nun frag ich mich wie ich das für einen String aus UNCODE Zeichen funktioniert. Also ich kann ja nicht alle UNICODE zeichen in base64_chars eintragen!?



  • Dir ist aber bekannt, dass alle sichtbaren ASCII-Zeichen in einem Bereich liegen? Ausgehend davon könntest du mit diesen Grenzen arbeiten. Wenn du unbedingt alle Zeichen in einem String benötigst, kannst du diesen entweder zur Laufzeit erstellen oder, wenn Geschwindigkeit vor Größe geht, dir vorher generieren lassen. Du musst aber jetzt nicht mehrere tausend Zeichen von Hand eintragen, was auch sehr fehleranfällig wäre.



  • ok, also hier im Beispiel verwende ich den String base64_chars zum verschlüsseln.

    Anstatt nurn wie hier diesen string zu definieren soll ich auf einen Bereich im speicher verweisen ab den die ASCII(in meinem Fall dann UNICDOE)-Zeichen definiert sind.

    Ok, angenommen ich finde diese Speicherstelle heraus, ist diese dann zwischen unterschiedlichen systemen überhaupt identisch (untersch. OS z.B. WindowsXP VISTA oder 7)



  • Nein, du hast das falsch verstanden. Die Zeichen in deinem base64_chars-String haben folgende Form "\x41\x42\x43\44 ... \x5A", was das selbe ist wie "ABCD ... Z". Wie du siehst ist A-Z nur ein Zahlenbereich von 41h bis 5Ah. Genauso verhält es sich mit den kleinen Buchstaben, Zahlen und auch den restlichen Unicode-Zeichen. Es gibt also kein Bedarf, alle Zeichen einzeln aufzuzählen. Wegen der Systemabhängigkeit brauchst du dir auch keine Gedanken machen. Die Werte sind exakt die selben, mit denen du jetzt auch arbeitest.



  • ok,
    habe verstanden. Vielen Dank.

    Bin eben dabei die Klasse zu erweitern und zwar um diese Methode:

    std::tstring getBaseString(){
        TCHAR aChar = '\x21';
        TCHAR aCompleteCharArray[94];
        aCompleteCharArray[0]=aChar;
        for(int i =0; i< ARRAY_SIZE(aCompleteCharArray); i++){
           aCompleteCharArray[i]=aChar;
           aChar = aChar+'\x1';
        }
        std::tstring base64_chars;
        base64_chars.assign(aCompleteCharArray, (ARRAY_SIZE(aCompleteCharArray)));
        //for(int i =0; i< base64_chars.length(); i++){
        //   cout<<i <<" " << base64_chars[i]<<endl;  
        //}
        return base64_chars;
    }
    

    Dies ist noch ein Beispiel für ASCII Zeichen. Wollte dafür einen string variabel erzeugen. Dabei werden alle Zeichen ab "\x21" bis "\x7E" verwendet.
    Das klappt aber schon einmal nicht. Also der String wird zwar verschlüsselt, aber nicht mehr korrekt entschlüsselt.



  • Ich kenne diesen tstring nicht, auch deine anderen Typen sind mir nicht geläufig. Aber willst du nicht nur einfach so was machen?

    std::string getBaseString()
    {
        std:string basestring;
    
        for (char character = '!'; character <= '~'; ++character)
        {
    	basestring += character;
        }
        return basestring;
    }
    


  • Nick Unbekannt schrieb:

    Ich kenne diesen tstring nicht, auch deine anderen Typen sind mir nicht geläufig. Aber willst du nicht nur einfach so was machen?

    #ifdef UNICODE
           #define cout wcout
           #define tstring wstring
           #define _TUCHAR wchar_t
    #else
           #define cout cout
           #define tstring string
           #define _TUCHAR unsigned char
    #endif
    

    da stehts 😉

    @TO: kennst _TCHAR nicht?

    typedef std::basic_string<_TCHAR> string_t;
    //typedef _TCHAR _TUCHAR;
    

    für cout / wcout weiß ich auch keine bessere möglichkeit als die hässlichen makros - aber vll weiß da jmd anderes ja mehr 😉

    könnt mir höchstens noch so was vorstellen:

    template <typename T>
    struct types;
    
    template <>
    struct types <char>
    {
      typedef char value_type;
      typedef std::string string_t;
    
      static std::ostream& out;
    };
    std::ostream& types<char>::out = std::cout;
    
    template <>
    struct types <wchar_t>
    {
      typedef wchar_t value_type;
      typedef std::wstring string_t;
    
      static std::wostream& out;
    }
    std::wostream& types<wchar_t>::out = std::wcout;
    
    int main()
    {
      types<_TCHAR>::string_t asd = _T("asd");
    
      types<_TCHAR>::out << asd;
    }
    

    aber so richtig toll find ichs auch nicht...

    bb



  • unskilled schrieb:

    da stehts 😉

    Ich hab mir am Anfang schon gedacht, wenn will er den mit seinen Umdefinierungen von cout verwirren. Und jetzt hab ich das Opfer gefunden. 😉
    Das ist aber auch zu verwirrend, wenn dann sein eigener tstring auch noch plötzlich im std-Namespace steckt.
    Für den Outputstream würde ich einfach einen typedef abhängig von UNICODE machen.

    #ifdef UNICODE
    typedef std::wcout mycout;
    #else
    typedef std::cout mycout;
    #endif
    

Log in to reply