Pour cacher du texte dans du texte(rtf). stéganographie. [borland 5, bcb]

Description

Vous souhaitez cacher un message sans que personne ne puisse soupçonner son existence : c'est possible !
Il y a plusieurs façons de faire. Ce programme montre comment cacher un texte non formaté dans un document au format RTF (Rich Text Format);

Désoler pour les puristes, comme je ne voulais me casser le tête pour les allocations de mémoire, je me suis servi de l'AnsiString de Borland pour mes chaînes de caractères. (Il faut faire le passage en char).

Le principe de basse est assez simple. On ce sert des lettres du document RTF pour cacher notre message. La taille est toujours fixée à 16 sauf quand on veut utilisé une lettre : cette dernière passe alors à 16,5.
C'est ce morceau de code que vous pouvez lire ci-dessous.
Pour le reste, l'interface graphique et les améliorations consulter le zip.

Dans quelques jours un autre type de stéganographie(Cacher des données dans des données) devrait voir le jour : Comment cacher un fichier quelconque dans une image BMP.

Source / Exemple :


AnsiString TexteO, TexteM; // Texte Original et Texte Modifié
long CaractereReste; // nombre de caratère restant à intègrer
long first; // fin de la config debut hypotètique du texte voir le zip ou l'initialiser à 0

void __fastcall TTexteChild::Integrer(void)
{
AnsiString t, tmp = " ", MessageO, CaractO;
long length, len, pass;
int ind, i, NCR;
bool caract;

    Compter();
    for (length=1;length<=TexteO.Length();length++) { // mise a la bonne taille des caractère
        if ((TexteO[length] == '\\') && (TexteO[length+1] == 'f') && (TexteO[length+2] == 's') && (TexteO[length+3] >= '0') && (TexteO[length+3] <= '9')) {
            t = t + "\\fs32";
            length+=2;
            while ((TexteO[length+1] != '\\') && (TexteO[length+1] != ' '))
                length++;
        } else {
            tmp[1] = TexteO[length];
            t = t + tmp;
        }
    }
    TexteM = t;
    t = "";

bool parant = false;

    for (length=1;length<=TexteM.Length();length++) { // supression des "{\fs09" "}"
        if ((TexteM[length] == '{') && (TexteM[length+1] == '\\') && (TexteM[length+2] == 'f') && (TexteM[length+3] == 's') && (TexteM[length+4] >= '0') && (TexteM[length+4] <= '9')) {
            length+=3;
            parant = true;
            while ((TexteM[length] != ' '))
                length++;
        } else if ((TexteM[length] == '}') && (TexteM[length-1] != '\\')){
            if (parant == false) {
                tmp[1] = TexteM[length];
                t = t + tmp;
            }
            parant = false;
        } else {
            tmp[1] = TexteM[length];
            t = t + tmp;
        }
    }
    TexteM = t;
    t = "";

    for (length=1;length<=Memo1->Text.Length();length++) { // enleve '\n'
        if (Memo1->Text[length] != '\n') {
            tmp[1] = Memo1->Text[length];
            MessageO = MessageO + tmp;
        }
    }

    len = MessageO.Length();

    if (len == 0) {
        CaractereReste = 0;
        goto fin;
    }

    tmp[1] = MessageO[1];
    CaractO = CharStrToRtf(tmp);
    MessageO = MessageO + " ";

    ind = 1;
    pass = 0;

    for (length=1;length<first;length++) {
        tmp[1] = TexteM[length];
        t = t + tmp;
    }
    for (length=first;length<=TexteM.Length();length++) {// integration
        if ((TexteM[length] == '\\') &&  // configuration du texte : ne pas toucher
            (!((TexteM[length+1] == '\'') || (TexteM[length+1] == '{') || (TexteM[length+1] == '}')))) {

             tmp[1] = TexteM[length];
             t = t + tmp;
             while ((TexteM[length+1] != '\\') && (TexteM[length+1] != ' ')) {
                length++;
                tmp[1] = TexteM[length];
                t = t + tmp;
             }
        } else { // c'est du texte visible

            if ( ((CaractO == " ") || (CaractO == "\r")) && (ind <= len)) { // 2 ou 3 caract visuel  ( 2 = ' ', 3 = "\r\n" = "\par"
                t = t + CaractereRtf(TexteM,length);

                if (CaractO == " ")
                    i = 2;
                else
                    i = 3;

                t = t + "\\fs33 ";
                while (i > 0) {
                    length++;
                    t = t + CaractereRtf(TexteM,length);
                    i--;
                }
                t = t + "\\fs32 ";

                ind++;
                tmp[1] = MessageO[ind];
                if ((tmp == "\r") || (tmp == " "))
                    CaractO = tmp;
                else
                    CaractO = CharStrToRtf(tmp);
                CaractereReste--;
                pass = 0;

            } else  {
                if ((TexteM[length] == CaractO[1]) && (ind <= len) && (pass > 3)) {
                    if (CaractO.Length() == 1) { // 1 caract visuel
                        t = t + "\\fs33 " + CaractO + "\\fs32 ";

                    } else {                    // plusieur caract formant 1 visuel
                        caract = true;
                        if (length+i < TexteM.Length()) {
                            i = CaractO.Length();
                            while (i > 2) {
                                if (CaractO[i] != TexteM[length+i-1]) {
                                    caract = false;
                                    break;
                                }
                                i--;
                            }
                        } else
                            caract = false;

                        if (caract == true) {
                            t = t + "\\fs33 " + CaractO + "\\fs32 ";
                        }
                    }

                    if ((CaractO.Length() == 1) || ((CaractO.Length() > 1) && (caract == true)) ) {
                        ind++;
                        tmp[1] = MessageO[ind];
                        if ((tmp == "\r") || (tmp == " "))
                            CaractO = tmp;
                        else
                            CaractO = CharStrToRtf(tmp);
                        CaractereReste--;
                        pass = 0;
                    }
                } else {
                    tmp[1] = TexteM[length];
                    t = t + tmp;
                    pass++;
                }
            }
        }
    }
    TexteM = t;
}
//---------------------------------------------------------------------------

void __fastcall TTexteChild::Extraire(void)
{
AnsiString t, tmp = " ";
long length;
bool Codee;

    Codee = true;
    for (length=1;length<=TexteO.Length();length++) { // le texte est-il bien codé
        if ((TexteO[length] == '\\') && (TexteO[length+1] == 'f') && (TexteO[length+2] == 's')) {
            if (!((TexteO[length+3] == '3') && (TexteO[length+4] >= '1') && (TexteO[length+4] <= '3'))) {
                Codee = false;
                break;
            }
        }
    }

    if (Codee == false) {
        Memo1->Text = ""; // il n'y a pas de message
        return;
    }

    for (length=1;length<=TexteO.Length();length++) {// extraction
         if ((TexteO[length] == '\\') &&  // mise en forme : ne pas toucher
             (!((TexteO[length+1] == '\'') || (TexteO[length+1] == '{') || (TexteO[length+1] == '}') ||
              ((TexteO[length+1] == 'f') && (TexteO[length+2] == 's') && (TexteO[length+3] >= '0') && (TexteO[length+3] <= '9'))
              ))) {
             while ((TexteO[length+1] != '\\') && (TexteO[length+1] != ' ')) {
                length++;
             }
         } else { // c'est du texte
             if ((TexteO[length] == '\\') && (TexteO[length+1] == 'f')  && (TexteO[length+2] == 's') && (TexteO[length+3] == '3') && (TexteO[length+4] == '3') && (TexteO[length+5] == ' ')) {
                switch (NbCaractRtf(TexteO,length,tmp))
                {
                  case 1 : t = t + tmp;
                  break;
                  case 2 : t = t + " ";
                  break;
                  case 3 : t = t + "\r\n";
                  break;
                }

             }
         }
    }

    TexteM = t;
}
//---------------------------------------------------------------------------

AnsiString __fastcall TTexteChild::CharStrToRtf(AnsiString Valeur)
{
AnsiString t;

    switch (Valeur[1])
    {
      case '{' : t = "\\{";
      break;
      case '}' : t = "\\}";
      break;
      case '\\' : t = "\\\\";
      break;
      case 'œ' : t = "\\'9c";
      break;
      case '¡' : t = "\\'a1";
      break;
      case '¢' : t = "\\'a2";
      break;
      case '£' : t = "\\'a3";
      break;
      case '?' : t = "\\'a4";
      break;
      case '¥' : t = "\\'a5";
      break;
      case 'S' : t = "\\'a6";
      break;
      case '§' : t = "\\'a7";
      break;
      case 's' : t = "\\'a8";
      break;
      case '©' : t = "\\'a9";
      break;
      case 'ª' : t = "\\'aa";
      break;
      case '®' : t = "\\'ae";
      break;
      case '¯' : t = "\\'af";
      break;
      case '°' : t = "\\'b0";
      break;
      case '±' : t = "\\'b1";
      break;
      case '²' : t = "\\'b2";
      break;
      case '³' : t = "\\'b3";
      break;
      case 'µ' : t = "\\'b5";
      break;
      case '·' : t = "\\'b7";
      break;
      case '¹' : t = "\\'b9";
      break;
      case 'º' : t = "\\'ba";
      break;
      case 'O' : t = "\\'bc";
      break;
      case 'o' : t = "\\'bd";
      break;
      case 'Y' : t = "\\'be";
      break;
      case '¿' : t = "\\'bf";
      break;
      case 'À' : t = "\\'c0";
      break;
      case 'Á' : t = "\\'c1";
      break;
      case 'Â' : t = "\\'c2";
      break;
      case 'Ã' : t = "\\'c3";
      break;
      case 'Ä' : t = "\\'c4";
      break;
      case 'Å' : t = "\\'c5";
      break;
      case 'Æ' : t = "\\'c6";
      break;
      case 'Ç' : t = "\\'c7";
      break;
      case 'È' : t = "\\'c8";
      break;
      case 'É' : t = "\\'c9";
      break;
      case 'Ê' : t = "\\'ca";
      break;
      case 'Ë' : t = "\\'cb";
      break;
      case 'Ì' : t = "\\'cc";
      break;
      case 'Í' : t = "\\'cd";
      break;
      case 'Î' : t = "\\'ce";
      break;
      case 'Ï' : t = "\\'cf";
      break;
      case 'Ð' : t = "\\'d0";
      break;
      case 'Ñ' : t = "\\'d1";
      break;
      case 'Ò' : t = "\\'d2";
      break;
      case 'Ó' : t = "\\'d3";
      break;
      case 'Ô' : t = "\\'d4";
      break;
      case 'Õ' : t = "\\'d5";
      break;
      case 'Ö' : t = "\\'d6";
      break;
      case '×' : t = "\\'d7";
      break;
      case 'Ø' : t = "\\'d8";
      break;
      case 'Ù' : t = "\\'d9";
      break;
      case 'Ú' : t = "\\'da";
      break;
      case 'Û' : t = "\\'db";
      break;
      case 'Ü' : t = "\\'dc";
      break;
      case 'Ý' : t = "\\'dd";
      break;
      case 'Þ' : t = "\\'de";
      break;
      case 'ß' : t = "\\'df";
      break;
      case 'à' : t = "\\'e0";
      break;
      case 'á' : t = "\\'e1";
      break;
      case 'â' : t = "\\'e2";
      break;
      case 'ã' : t = "\\'e3";
      break;
      case 'ä' : t = "\\'e4";
      break;
      case 'å' : t = "\\'e5";
      break;
      case 'æ' : t = "\\'e6";
      break;
      case 'ç' : t = "\\'e7";
      break;
      case 'è' : t = "\\'e8";
      break;
      case 'é' : t = "\\'e9";
      break;
      case 'ê' : t = "\\'ea";
      break;
      case 'ë' : t = "\\'eb";
      break;
      case 'ì' : t = "\\'ec";
      break;
      case 'í' : t = "\\'ed";
      break;
      case 'î' : t = "\\'ee";
      break;
      case 'ï' : t = "\\'ef";
      break;
      case 'ð' : t = "\\'f0";
      break;
      case 'ñ' : t = "\\'f1";
      break;
      case 'ò' : t = "\\'f2";
      break;
      case 'ó' : t = "\\'f3";
      break;
      case 'ô' : t = "\\'f4";
      break;
      case 'õ' : t = "\\'f5";
      break;
      case 'ö' : t = "\\'f6";
      break;
      case '÷' : t = "\\'f7";
      break;
      case 'ø' : t = "\\'f8";
      break;
      case 'ù' : t = "\\'f9";
      break;
      case 'ú' : t = "\\'fa";
      break;
      case 'û' : t = "\\'fb";
      break;
      case 'ü' : t = "\\'fc";
      break;
      case 'ý' : t = "\\'fd";
      break;
      case 'þ' : t = "\\'fe";
      break;
      case 'ÿ' : t = "\\'ff";
      break;
      case '\r' : t = "\\par\r";
      break;
      default: t = Valeur;
    }

    return t;
}
//---------------------------------------------------------------------------

AnsiString __fastcall TTexteChild::CaractereRtf(AnsiString TextRTF, long &Position)
{
long pos;
AnsiString CarRtf, tmp = " ";
bool fin;

    pos = Position;
    fin = false;
    do {
        tmp[1] = TextRTF[pos];
        CarRtf = CarRtf + tmp;
        switch (TextRTF[pos])
        {
          case '\\': pos++;
                tmp[1] = TextRTF[pos];
                switch (TextRTF[pos])
                {
                  case '{': ;
                  case '}': ;
                  case '\\': CarRtf = CarRtf + tmp;
                        fin = true;
                  break;
                  case '\'': tmp = "  ";
                        tmp[1] = TextRTF[pos+1];
                        tmp[2] = TextRTF[pos+2];
                        CarRtf = CarRtf + HexToInt(tmp);
                        tmp = " ";
                        pos+=2;
                        fin = true;
                  break;
                  case '~': pos++;
                  break;
                 default:
                        while((TextRTF[pos] != ' ') && (TextRTF[pos] != '\r') && (TextRTF[pos] != '\\')) {
                            tmp[1] = TextRTF[pos++];
                            CarRtf = CarRtf + tmp;
                        }
                }

          break;
          case ' ': ;
          case '\r': ;
          case '\n': pos++;
          break;
          default: fin = true;
        }

    } while(fin == false);

    Position = pos;
    return CarRtf;

}
//---------------------------------------------------------------------------

int __fastcall TTexteChild::NbCaractRtf(AnsiString TextRTF, long pos, AnsiString &Caract)
{
int nb;
AnsiString fs32, tmp = " ";
bool fin;

    nb = 0;
    Caract = " ";
    do {
        switch (TextRTF[pos])
        {
          case '\\': pos++;
                fs32 = "";
                switch (TextRTF[pos])
                {
                  case '{': ;
                  case '}': ;
                  case '\\': nb++;
                  case '~': pos++; // '°' => espace fait par word avant '!' et '?'
                  break;
                  case '\'': pos++;
                  break;
                  default:
                        while((TextRTF[pos] != ' ') && (TextRTF[pos] != '\r') && (TextRTF[pos] != '\\')) {
                            tmp[1] = TextRTF[pos++];
                            fs32 = fs32 + tmp;
                        }
                }

          break;
          case ' ': ;
          case '\r': ;
          case '\n': pos++;
          break;
          default: nb++;
                pos++;
        }
        if ((nb == 1) && (fs32 != "fs32"))
            Caract[1] = TextRTF[pos-1];

    } while(fs32 != "fs32");

    return nb;

}
//---------------------------------------------------------------------------

const AnsiString Hexa = "0123456789ABCDEF";

double __fastcall TTexteChild::HexToInt(AnsiString Valeur)
{
double exp, convert;
int i, curs;

    Valeur = Valeur.UpperCase();
    exp = 1;
    convert = 0;
    for( i=Valeur.Length(); i>0; i--) {
        curs = 1;
        while( Valeur[i] != Hexa[curs]) curs++;
        convert += (curs-1) * exp;
        exp *= 16;
    }
    return convert;
}
//---------------------------------------------------------------------------

Conclusion :


On pourrait ajouter des options de cryptographie, je le ferais peut-être.

Pendant les vacances scolaires je suis pas souvent sur le net, alors je repondrai quand même à vos questions mais avec du retard.
25/06/2004

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.