/*************************************************************************************************************************************/
/* */
/* 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
Copyright © Jean-François COLONNA, 2019-2024.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2019-2024.