/*************************************************************************************************************************************/ /* */ /* C H I F F R A G E S T E G A N O G R A P H I Q U E : */ /* */ /* */ /* Author of '$xcg/chiffrage.21$K' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 1996??????????). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* I N T E R F A C E ' listG ' : */ /* */ /* */ /* :Debut_listG: */ /* :Fin_listG: */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D I R E C T I V E S S P E C I F I Q U E S D E C O M P I L A T I O N : */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* F I C H I E R S D ' I N C L U D E S : */ /* */ /*************************************************************************************************************************************/ #include INCLUDES_MINI /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* P A R A M E T R E S : */ /* */ /*************************************************************************************************************************************/ #define CHIFFRER \ VRAI \ /* Faut-il chiffrer ('VRAI') ou dechiffrer ('FAUX'). */ #define DEFINIR_LE_TEXTE_AVEC_UNE_CHAINE_DE_CARACTERES \ VRAI \ /* Faut-il definir le texte a chiffrer avec une chaine de caracteres ('VRAI') ou bien */ \ /* avec un fichier ('FAUX'). On notera le 20051110114231 l'interet de passer par un */ \ /* fichier (surtout s'il est dans '$DStemporaires' -en ce qui concerne des MACHINEs telle */ \ /* '$CMAP28' dont le File System supporte des "snapshots" ce qui rend difficile de se */ \ /* debarasser rapidement des fichiers detruits- et detruit apres usage) : en effet, le texte */ \ /* a chiffrer n'apparait alors pas dans l'history de la MACHINE, ce qui est necessaire pour */ \ /* des raisons evidentes de securite... */ #define PREMIER_CARACTERE_A_MODIFIER \ QUARANTE \ /* Index du premier caractere du fichier Argument a modifier (eviter les puissances de 2). */ #define DERNIER_CARACTERE_A_MODIFIER \ INFINI \ /* Index du dernier caractere du fichier Argument a modifier (eviter les puissances de 2). */ #define PAS_DES_INDEX_DES_CARACTERES_A_MODIFIER \ CINQUANTE \ /* Pas de passage d'un caractere a modifier au suivant (eviter les puissances de 2), */ \ /* sachant qu'un seul bit est modifie par caractere... */ #define POIDS_DU_BIT_A_UTILISER \ BIT0 \ /* Donne le poids du bit a utiliser (a priori, celui de poids le plus faible...). */ #define CARACTERE_DE_REMPLISSAGE \ K_NULL \ /* Afin de mettre a la suite du texte a cacher lorsqu'il est trop court... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M A C R O S U T I L E S : */ /* */ /*************************************************************************************************************************************/ #define TAILLE_EFFECTIVE_DU_TEXTE_A_CHIFFRER \ COND(IL_FAUT(definir_le_texte_avec_une_chaine_de_caracteres) \ ,chain_Xtaille(texte_a_chiffrer) \ ,nombre_de_caracteres_du_fichier_definissant_le_texte_a_chiffrer \ ) \ /* Taille effective du texte a chiffrer en fonction de sa provenance. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C H I F F R A G E S T E G A N O G R A P H I Q U E : */ /* */ /*************************************************************************************************************************************/ BCommande(nombre_d_arguments,arguments) /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Logical,INIT(chiffrer,CHIFFRER)); /* Faut-il chiffrer ('VRAI') ou dechiffrer ('FAUX'). */ DEFV(Logical,INIT(definir_le_texte_avec_une_chaine_de_caracteres,DEFINIR_LE_TEXTE_AVEC_UNE_CHAINE_DE_CARACTERES)); /* Faut-il definir le texte a chiffrer avec une chaine de caracteres ('VRAI') ou bien */ /* avec un fichier ('FAUX'). On notera le 20051110114231 l'interet de passer par un */ /* fichier (surtout s'il est dans '$DStemporaires' -en ce qui concerne des MACHINEs telle */ /* '$CMAP28' dont le File System supporte des "snapshots" ce qui rend difficile de se */ /* debarasser rapidement des fichiers detruits- et detruit apres usage) : en effet, le texte */ /* a chiffrer n'apparait alors pas dans l'history de la MACHINE, ce qui est necessaire pour */ /* des raisons evidentes de securite... */ DEFV(CHAR,INIC(POINTERc(nom_fichier),NOM_PIPE)); DEFV(Int,INIT(nombre_de_caracteres_du_fichier_definissant_le_texte_a_chiffrer,UNDEF)); /* Definition du fichier contenant le texte a chiffre si besoin est, c'est-a-dire si */ /* 'IL_NE_FAUT_PAS(definir_le_texte_avec_une_chaine_de_caracteres)'. */ DEFV(Logical,INIT(editer_les_messages_d_erreur,EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS)); /* Indicateur a utiliser pour editer les messages d'erreur des fichiers. */ DEFV(Int,INIT(premier_caractere_a_modifier,PREMIER_CARACTERE_A_MODIFIER)); /* Index du premier caractere du fichier Argument a modifier (eviter les puissances de 2). */ DEFV(Int,INIT(dernier_caractere_a_modifier,DERNIER_CARACTERE_A_MODIFIER)); /* Index du dernier caractere du fichier Argument a modifier (eviter les puissances de 2). */ DEFV(Int,INIT(pas_des_index_des_caracteres_a_modifier,PAS_DES_INDEX_DES_CARACTERES_A_MODIFIER)); /* Pas de passage d'un caractere a modifier au suivant (eviter les puissances de 2), */ /* sachant qu'un seul bit est modifie par caractere... */ DEFV(Int,INIT(poids_du_bit_a_utiliser,POIDS_DU_BIT_A_UTILISER)); /* Donne le poids du bit a utiliser (a priori, celui de poids le plus faible...). */ DEFV(CHAR,INIC(POINTERc(texte_a_chiffrer),C_VIDE)); /* Texte a chiffrer grace a une methode steganographique. */ DEFV(Int,INIT(caractere_courant_de_fichierA,UNDEF)); DEFV(Int,INIT(index_du_caractere_courant_de_fichierA,PREMIER_CARACTERE)); /* Donnees du fichier Argument. */ /* ATTENTION, on utilise 'Int' et non pas 'Char' pour 'caractere_courant_de_fichierA' a */ /* cause de l'usage qui sera fait ci-apres de 'GetcharQ(...)', et ce afin que le test de */ /* fin de fichier fonctionne correctement... */ DEFV(CHAR,INIT(caractere_courant_de_fichierR,K_NULL)); DEFV(Int,INIT(index_du_caractere_courant_du_texte_a_chiffrer,PREMIER_CARACTERE)); DEFV(Int,INIT(amplitude_du_decalage,ZERO)); /* Donnees du fichier Resultat. */ DEFV(CHAR,INIT(caractere_de_remplissage,CARACTERE_DE_REMPLISSAGE)); /* Afin de mettre a la suite du texte a cacher lorsqu'il est trop court... */ /*..............................................................................................................................*/ GET_ARGUMENTS_(nombre_d_arguments ,BLOC(GET_ARGUMENT_L("chiffrer=",chiffrer); GET_ARGUMENT_N("dechiffrer=",chiffrer); /* Parametre introduit le 20051110112911... */ GET_ARGUMENT_L("definition_par_chaine=""dc=""chaine=",definir_le_texte_avec_une_chaine_de_caracteres); GET_ARGUMENT_C("texte=""message=""chaine_a_chiffrer=",texte_a_chiffrer); /* Parametre introduit le 20051110113057... */ GET_ARGUMENT_N("df=""definition_par_fichier=",definir_le_texte_avec_une_chaine_de_caracteres); GET_ARGUMENT_C("fichier=""fichier_a_chiffrer=""f=""F=",nom_fichier); GET_ARGUMENT_L("erreurs=",editer_les_messages_d_erreur); GET_ARGUMENT_I("premier=",premier_caractere_a_modifier); GET_ARGUMENT_I("dernier=",dernier_caractere_a_modifier); GET_ARGUMENT_I("pas=",pas_des_index_des_caracteres_a_modifier); GET_ARGUMENT_I("poids=",poids_du_bit_a_utiliser); GET_ARGUMENT_K("remplissage=",caractere_de_remplissage); ) ); Test(IFEXff(poids_du_bit_a_utiliser,BIT0,TRMU(NBITOC))) Bblock PRINT_ERREUR("le poids du bit a utiliser est inexistant"); CAL1(Prer1("(la valeur par defaut (%d) est forcee)\n",POIDS_DU_BIT_A_UTILISER)); EGAL(poids_du_bit_a_utiliser,POIDS_DU_BIT_A_UTILISER); Eblock ATes Bblock Eblock ETes Test(IL_FAUT(chiffrer)) Bblock Test(IL_FAUT(definir_le_texte_avec_une_chaine_de_caracteres)) Bblock Eblock ATes Bblock CALS(Fsize_fichier(nom_fichier ,ADRESSE(nombre_de_caracteres_du_fichier_definissant_le_texte_a_chiffrer) ,editer_les_messages_d_erreur ) ); /* Nombre de caracteres du fichier definissant le texte a chiffrer... */ EGAL(texte_a_chiffrer,kMalo(nombre_de_caracteres_du_fichier_definissant_le_texte_a_chiffrer)); /* Allocation de la memoire temporaire necessaire. */ CALS(Fload_fichier_non_formatte(nom_fichier ,texte_a_chiffrer ,nombre_de_caracteres_du_fichier_definissant_le_texte_a_chiffrer ,size_char ,editer_les_messages_d_erreur ,editer_les_messages_d_erreur ) ); /* Chargement du fichier definissant le texte a chiffrer... */ Eblock ETes EGAL(index_du_caractere_courant_du_texte_a_chiffrer,PREMIER_CARACTERE); /* Initialisation (a priori inutile) de l'index du texte a chiffrer... */ Repe(TAILLE_EFFECTIVE_DU_TEXTE_A_CHIFFRER) Bblock Test(IFEQ(ITb0(texte_a_chiffrer,INDX(index_du_caractere_courant_du_texte_a_chiffrer,PREMIER_CARACTERE)) ,caractere_de_remplissage ) ) Bblock PRINT_ERREUR("le texte a chiffrer contient le caractere de remplissage"); CAL1(Prer1("(son code est %02X)\n",caractere_de_remplissage)); Eblock ATes Bblock Eblock ETes INCR(index_du_caractere_courant_du_texte_a_chiffrer,I); /* Progression de l'index du texte a chiffrer... */ Eblock ERep EGAL(index_du_caractere_courant_du_texte_a_chiffrer,PREMIER_CARACTERE); /* Re-initialisation de l'index du texte a chiffrer... */ Tant(GetcharQ(caractere_courant_de_fichierA)) Bblock /* Le caractere courant de l'entree courante est recupere ; et on boucle */ /* sur cette recuperation tant que l'on n'est pas au bout du fichier. */ Test(IFET(IFINff(index_du_caractere_courant_de_fichierA,premier_caractere_a_modifier,dernier_caractere_a_modifier) ,DIVISIBLE(SOUS(index_du_caractere_courant_de_fichierA,premier_caractere_a_modifier) ,pas_des_index_des_caracteres_a_modifier ) ) ) Bblock EGAL(caractere_courant_de_fichierR ,OUIN(ETLO(caractere_courant_de_fichierA ,OUEX(MOCD ,SLLS(BIT,poids_du_bit_a_utiliser) ) ) ,SLLS(ETLO(SLRS(COND(IFLE(index_du_caractere_courant_du_texte_a_chiffrer ,LSTX(PREMIER_CARACTERE,TAILLE_EFFECTIVE_DU_TEXTE_A_CHIFFRER) ) ,ITb0(texte_a_chiffrer ,INDX(index_du_caractere_courant_du_texte_a_chiffrer,PREMIER_CARACTERE) ) ,caractere_de_remplissage ) ,amplitude_du_decalage ) ,BIT ) ,poids_du_bit_a_utiliser ) ) ); /* Cas ou le caractere courant du fichier Argument doit etre chiffre... */ INCR(amplitude_du_decalage,LBIT); /* Passage au bit suivant du texte a chiffrer... */ Test(IFGE(amplitude_du_decalage,NBITOC)) Bblock EGAL(amplitude_du_decalage,ZERO); INCR(index_du_caractere_courant_du_texte_a_chiffrer,I); /* Lorsque l'on "sort" du caractere courant, on passe au suivant... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock EGAL(caractere_courant_de_fichierR ,caractere_courant_de_fichierA ); /* Cas ou le caractere courant du fichier Argument n'est pas chiffre... */ Eblock ETes CALS(Putchar(caractere_courant_de_fichierR)); /* Le caractere courant est emis... */ INCR(index_du_caractere_courant_de_fichierA,I); /* Index du caractere suivant... */ Eblock ETan Test(IFLE(index_du_caractere_courant_du_texte_a_chiffrer,LSTX(PREMIER_CARACTERE,TAILLE_EFFECTIVE_DU_TEXTE_A_CHIFFRER))) Bblock PRINT_ERREUR("tous les bits n'ont pas ete codes"); Eblock ATes Bblock /* Cas ou il n'y a rien a recuperer : il n'y a donc rien a faire... */ Eblock ETes Eblock ATes Bblock Tant(GetcharQ(caractere_courant_de_fichierA)) Bblock /* Le caractere courant de l'entree courante est recupere ; et on boucle */ /* sur cette recuperation tant que l'on n'est pas au bout du fichier. */ Test(IFET(IFINff(index_du_caractere_courant_de_fichierA,premier_caractere_a_modifier,dernier_caractere_a_modifier) ,DIVISIBLE(SOUS(index_du_caractere_courant_de_fichierA,premier_caractere_a_modifier) ,pas_des_index_des_caracteres_a_modifier ) ) ) Bblock EGAL(caractere_courant_de_fichierR ,OUIN(SLLS(SLRS(ETLO(caractere_courant_de_fichierA ,SLLS(BIT,poids_du_bit_a_utiliser) ) ,poids_du_bit_a_utiliser ) ,amplitude_du_decalage ) ,caractere_courant_de_fichierR ) ); /* Cas ou il y a un bit a recuperer dans le caractere courant... */ INCR(amplitude_du_decalage,LBIT); /* Passage au bit suivant du texte a chiffrer... */ Test(IFGE(amplitude_du_decalage,NBITOC)) Bblock Test(IFNE(caractere_courant_de_fichierR,caractere_de_remplissage)) Bblock CALS(Putchar(caractere_courant_de_fichierR)); /* Le caractere courant est emis a condition que ce ne soit pas un 'NULL' auquel cas, il */ /* correspond a du remplissage a la suite du texte cache... */ Eblock ATes Bblock Eblock ETes EGAL(caractere_courant_de_fichierR,K_NULL); /* Preparation du caractere suivant... */ EGAL(amplitude_du_decalage,ZERO); INCR(index_du_caractere_courant_du_texte_a_chiffrer,I); /* Lorsque l'on "sort" du caractere courant, on passe au suivant... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock /* Cas ou il n'y a rien a recuperer : il n'y a donc rien a faire... */ Eblock ETes INCR(index_du_caractere_courant_de_fichierA,I); /* Index du caractere suivant... */ Eblock ETan Test(IZNE(amplitude_du_decalage)) Bblock /* ATTENTION, ce n'est pas une erreur car, en effet, rien ne prouve que le nombre de */ /* caracteres du fichier Argument soit (a une translation pres) divisible par le pas... */ Eblock ATes Bblock Eblock ETes Eblock ETes RETU_Commande; Eblock ECommande