You are on page 1of 92

Universit de Nmes

Licence 3 Mathmatiques Informatique


Module Projet Informatique
Anne 2008-2009
Enseignant : Marc Chaumont
Utilisation des codes correcteurs derreurs en
st eganographie :
De lalgorithme F5 et sa st eganalyse aux codes ` a
papier mouill e
Rmi Watrigant
Table des matires
1 Introduction 3
2 La stganographie en gnral 4
2.1 Dnition dun schma de stganographie . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Attaque dun schma de stganographie . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 Scurit dun schma de stganographie . . . . . . . . . . . . . . . . . . . . . . . . . 6
3 Quelques techniques de stganographie 8
3.1 Technique LSB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.1.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.1.2 Inconvnients, attaque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Matrix embedding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2.1 Point de vue intuitif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2.2 Gnralisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.3 Ecacit dinsertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.3 Codes papier mouill . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.3.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4 Lalgorithme F5 19
4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.2 Compression JPEG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.3 Description de lalgorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.4 Attaque de lalgorithme F5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.5 Implmentations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.6 Implmentation et rsultats de lalgorithme F5 . . . . . . . . . . . . . . . . . . . . . 24
4.7 Implmentation et rsultats de lattaque de lalgorithme F5 . . . . . . . . . . . . . . 27
5 Conclusion 29
6 Rfrences bibliographiques 30
A Fichiers source 31
A.1 DCTCoef.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
A.2 DCTCoef.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
A.3 compress.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
A.4 Embedding.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
A.5 Embedding.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
A.6 Extraction.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
A.7 Extraction.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
A.8 mainEmbed.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
A.9 mainExtract.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
A.10 attack.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
A.11 makele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
2
1 Introduction
Ce dossier est le compte-rendu du projet eectu durant le second semestre de ma troisime
anne de Licence Mathmatiques-Informatique, luniversit de Nmes, dans un module dirig par
M. Chaumont.
Ce projet a consist tudier les principes de la stganographie adapate aux images. Cette der-
nire est dnie comme lart consistant insrer un message dans une image, en cachant lexistence
mme du message. Elle se direncie du tatouage par le rle de lattaquant au sein des schmas.
La stganographie existe depuis de nombreuses annes, avec des techniques comme lencre invisible
(apparu au 1er sicle avant J-C), ou par la technique du micropoint de Zapp, utilis pendant la
deuxime guerre mondiale par les allemands, consistant rduire la taille dune photo en un point
pouvant tre insr dans du texte, la place des points des i par exemple. De nos jours, et particuli-
rement durant les deux dernires dcennies, avec lessor dInternet, la stganographie sest adapate
aux formats numriques, et notamment dans les images, qui sont normment partages sur la
toile. Elle est utilise par toutes les personnes cherchant communiquer des messages discrtement,
comme par exemple larme, ou les organisations terroristes. Cependant, tudier les techniques de
stganographie amne galement tudier les techniques de stganalyse : lart dattaquer les sch-
mas de stganographie, et donc de dterminer la prsence ou non de messages cachs au sein des
supports. La stganographie est donc un domaine de recherche de plus en plus tudi de nos jours.
Je me suis intress ce projet car il traite de nombreux domaines qui mintressent : la thorie
de linformation, avec la communication au sein de canaux non srs, et le traitement dimages,
notamment en domaine frquentiel.
Je remercie M. Chaumont pour laide quil ma apport dans la comprhension des concepts, et
pour avoir mis ma disposition de la littrature et des codes sources sur le sujet.
La partie 2 traite du concept de stganographie en gnral, dans le contexte des formats num-
riques. La partie 3 dcrit une technique de stganographie utilisant la thorie des codes correcteurs,
avec notamment deux applications : les codes de Hamming, et les codes papier mouill. Enn,
la partie 4 traite dune implmentation dun schma de stganographie et de son attaque : lalgo-
rithme F5. Elle contient galement la prsentation de mes implmentations et quelques rsultats
exprimentaux. Le dossier est conclu partie 5, et les codes sources sont disponibles en annexe.
3
2 La stganographie en gnral
2.1 Dnition dun schma de stganographie
De manire intuitive, la stganographie peut se rsumer lhistoire suivante :
Alice et Bob sont en prison, enferms dans deux cellules spares lune de lautre, et souhaite-
raient plannier une vasion. Ils sont autoriss communiquer par le biais de messages surveills,
an quils ne discutent pas dun plan pour schapper. La personne qui surveille les messages est
Eve, la gardienne. Si Eve dtecte le moindre signe de conspiration, elle transfrera Alice et Bob dans
des prisons de haute scurit, do personne na jamais pu svader... Alice et Bob sont conscients
de a, et ont par consquent partag un secret commun avant dtre enferms, quils vont utiliser
an de cacher leur plan dans des messages innocents. Les projets dAlice et Bob russiront sils
arrivent schanger des informations an de schapper de la prison, sans que Eve soit suspicieuse.
Aprs avoir dcrit la stganographie de manire intuitive, nous allons maintenant nous intresser
son formalisme mathmatique et une description plus prcise.
Un schma stganographique est la donne de deux fonctions et dune ou plusieurs cls. De la
mme manire quen cryptographie, on peut discerner deux types de stganographie : cl prive
et cl publique. Dans le cas dun algorithme de stganographie cl prive, lmetteur, Alice, et
le rcepteur, Bob, utilisent un canal scuris (ou bien un systme de partage de secret robuste) an
de dnir une cl prive commune, qui sera utilise pour insrer un message et pour lextraire. Dans
le cas dun algorithme cl publique, lemetteur dispose dune cl publique pour insrer le message,
et le rcepteur dune cl prive, lui seul pouvant ainsi extraire le message (Dans la pratique, la cl
prive est le plus souvent limage de la cl publique par une fonction dite sens unique).
Nous ne nous intresserons ici uniquement des algorithmes cl prive.
Dans la suite de ce dossier, nous utiliserons les notations suivantes :
K reprsente lensemble des cls possibles, M reprsente lensemble des messages possibles
insrer, et C lensemble de tous les supports possibles.
Un schma stganographique est dnie par deux fonctions : Emb : C M K C qui est la
fonction dinsertion (embedding), qui prend en paramtre un support, un message et une cl prive,
et retourne un lment de C, et Ext : C K M qui est la fonction dextraction.
Le but dun schma stganographique est de retrouver un message insr dans un support. Ceci
se traduit mathmatiquement par lgalit : Ext(Emb(c, m, k), k) = m, (c, m, k) C M K.
Le rsultat de la fonction emb est habituellement appel stgo-medium, ou stego-work, et le support
c est appel mdium, ou cover-work. Le fonctionnement dun schma de stganographie est rsum
par la gure 1.
Les algorithmes tudis dans ce projet sont destins insrer des messages de type texte dans
des images. Ainsi, on assimile lensemble des messages M lensemble F
l
2
= {0, 1}
l
, l tant la
taille du message en bits, et F
2
tant le corps de Galois deux lments, en prenant par exemple
pour chaque caractre la reprsentation en base 2 de son code ASCII (nombre entre 0 et 255). De
mme, on assimile lensemble des supports C F
n
2
= {0, 1}
n
, n tant la taille du support en bits,
laide dune certaine fonction, par exemple en prenant la valeur du LSB (Least Signicant Bit :
bit de poids faible, cest dire le bit se trouvant le plus droite dans la reprsentation dun nombre
entier en binaire) de la composante lumineuse de chaque pixel de limage.
Certains algorithmes utilisent en plus une technique de cryptographie, en insrant alors non pas
le message en lui mme, mais le cryptogramme associ celui-ci par un algorithme de cryptographie.
Le but de cette technique et dajouter une scurit supplmentaire au schma, en empchant de
retrouver le message dans le cas dune detection de linsertion par un attaquant. Cependant, la
stganographie consistant cacher lexistence mme du message, lutilisation de cryptographie est
facultative et na pas besoin dexister si le schma stganographique est sr. Ainsi, nous ne nous
4
Fig. 1 Schma des fonctions dinsertion et dextraction dun message dans une image
intresserons pas lajout dune technique de cryptographie dans les algorithmes tudis.
2.2 Attaque dun schma de stganographie
Cette section aborde la stganalyse : les systmes visants attaquer les systmes de stgano-
graphie.
Tout dabord, si la stganographie vise cacher lexistence dun message dans un support, alors
le stganalyste cherche en premier dterminer, pour un support donn, si celui-ci est porteur
dun message ou non. Lattaquant donne donc une rponse binaire (ou une probabilit) selon si un
message a t insr ou non.
Ensuite, dans le cas dune rponse positive au test prcdent, le stganalyste peut alors chercher
extraire le plus dinformation concernant le message insr, et dans le meilleur des cas, extraire
le message en lui mme.
Enn, sil y a eu cryptographie lors de linsertion, alors lattaquant doit cryptanalyser le message
extrait.
Nous nous plaons ici dans le cas dun attaquant passif. En reprenant lexemple de lintroduc-
tion, Eve est donc le gardien, et contrle les changes entre les deux prisonniers Alice et Bob, sans
les modier (do le terme passif). Eve sait videmment ce qui constitue une communication l-
gitime ou non entre les deux prisonniers, et connait galement les spcications des techniques de
stganographie utilises. Ce quil ignore en revanche, cest la cl secrte partage par Alice et Bob.
Ainsi, deux approches peuvent tre distingues : une attaque par recherche exhaustive sur la cl,
et une attaque par analyse de la lgitimit de lchange. La premire tant irralisable en pratique,
nous allons nous intresser la seconde.
Lattaque par analyse de la lgitimit de lchange consiste dans notre cas eectuer une mesure
sur limage intercepte, et comparer cette mesure avec celle dune image non stganographie. L
5
encore, deux possibilits sorent au stganalyste : une attaque cible ou non cible.
Une attaque cible consiste tudier en profondeur une technique prcise, et mettre en va-
leur une proprit caractristique des limages aprs linsertion dun message. Nous tudierons un
exemple dattaque cible dans la section 4.4 page 22, dans le cas de lalgorithme F5.
Une attaque non cible, elle, consiste construire un systme de discrimination : tout dabord, le
systme doit apprendre et classer des quantits dimages dont on sait si elles ont t stganographie
ou non (par nimporte quel algorithme de stganographie, do le terme non cible). Ensuite, le
systme peut dresser une frontire entre les images porteuses dun message et les images normales,
et ainsi dterminer dans quelle classe se trouve une image intercepte. Ce genre de systme porte
le nom de Machines Support Vectoriel (SVM).
La prise en compte de ces attaques, notamment les attaques cibles, peuvent servir tablir un
critre de scurit dans les schmas stganographiques. Ce critre de scurit, ainsi que dautres
plus gnraux, sont dcrits dans la partie suivante.
2.3 Scurit dun schma de stganographie
Le but dun schma stganographique est dinsrer un message dans un support, en cachant
lexistence mme de ce message. Ainsi, on peut discerner deux critres dvaluation :
la capacit.
lindtectabilit de ce message.
Il est vident de remarquer premire vue que ces deux critres sont en opposition : plus le
message est gros, plus il sera dicile cacher. Lemetteur et le recepteur vont donc devoir trouver un
compromis entre la capacit et lindetectabilit an de construire un bon schma stganographique.
Concernant la capacit, plusieurs mesures sont utilises. Tout dabord la capacit dinsertion,
dnie par log
2
|M|, |M| tant le nombre de message possibles. On peut galement dnir la capacit
dinsertion relative, qui est la capacit divis par la taille du support. Enn, le critre le plus
utilis est lecacit dinsertion (embedding eciency), qui est par dnition le nombre de bits
insrs pour une modication dans le support. Evidemment, plus ce nombre est grand, plus nous
avons la possibilit dinsrer un grand nombre de bits dans le message, car il y aura alors peu de
modications, donc peu de dtection. Cependant, le nombre de modications apportes au support
nest pas directement le critre le plus adapt pour caractriser la scurit dun schma. En eet,
nous allons voir que la manire de le modier est plus importante pour prserver lindtectabilit
des donnes caches.
La notion dindtectabilit se rfre la rsistance une attaque cible. Ce critre a t adapt
des concepts de la thorie de linformation, et ennonc pour la premire fois par Cachin dans [4].
An de dterminer la scurit dun systme, nous allons comparer la distribution dun support,
avant et aprs insertion.
En eet, soit c un support de couverture de distribution de probabilit P
c
, assimil une va-
riable alatoire sur lalphabet , et s, de distribution de probabilit P
s
, limage de c par la fonction
dinsertion dun schma stganographique. La scurit de ce schma est alors dpendante des simi-
litudes entre P
c
et P
s
. Plus prcisment, Cachin utilise lentropie relative des deux distributions de
probabilit pour dnir ce critre. Cette distance (qui nest pas une distance au sens mathmatique
du terme, car non symtrique) est dnie par :
D(P
c
||P
s
) =

i
P
c
(i)log
2
P
c
(i)
P
s
(i)
Le schma est alors considr comme sr si D(P
c
||P
s
) = 0, et considr comme -sr si
D(P
c
||P
s
) < .
6
An de mieux comprendre le terme de -sr, plaons nous du ct de lattaquant. Considrons
que celui-ci peut commettre deux erreurs lors de linterception dun message
1
entre Alice et Bob :
Erreur 1 : le message est considr comme illgal alors quil ne contient pas de donnes caches.
Supposons la probabilit de cette erreur gale .
Erreur 2 : le message est considr comme lgal alors quil contient des donnes caches. Sup-
posons la probabilit de cette erreur gale .
Face un message intercept, lattaquant doit rpondre 0 (message lgal) ou 1 (message illgal).
Alors :
face un message lgal, lattaquant va rpondre 1 avec une probabilit gale alpha, et 0
avec une probabilit gale 1 .
face un message illgal, lattaquant va rpondre 1 avec une probabilit gale 1 , et 0
avec une probabilit gale .
Alors lentropie relative entre les deux distributions du detecteur de lattaquant est gale :
D(||) = (1 )log
2
1

+ log
2

1
(1)
et rsultants de traitements sur P
c
et P
s
, leur entropie relative ne peut pas tre suprieure
D(P
c
||P
s
). Ainsi on a :
D(||) D(P
c
||P
s
) (2)
Si lon xe = 0, cest dire que lon interdit lattaquant de considrer des messages illgaux
alors quils sont lgaux, lquation 1 devient : D(||) = log
2
1

.
Ainsi, lquation 2 devient :
log
2
1

D(P
c
||P
s
)
Or, comme D(P
c
||P
s
) < , on a :
log
2
1

<
ce qui quivaut
> 2

Ainsi, plus est petit, plus la probabilit quun message illgal ne soit pas dtect est grande.
Le terme -sr prend donc ici tout son sens dans lexpression du critre de scurit dun schma
stganographique.
1
Ici, le mot message correspond aux donnes circulant sur le canal non scuris, et non pas aux donnes insres
dans le support, comme dni dans la section prcdente. Nous parlerons dun message lgal pour un message ne
contenant pas de donnes caches, illgal pour le contraire.
7
3 Quelques techniques de stganographie
3.1 Technique LSB
3.1.1 Description
La premire technique de stganographie tudie est un exemple trs simpliste de ce que peut
tre un schma de stganographie. Cest aussi un trs bon exemple de systme non sr, o nous
pourrons appliquer les principes vus dans la section prcdente.
Cet algorithme ncessite dabord de convertir limage en une suite de nombre binaires. Pour
cela, nous pouvons par exemple prendre la reprsentation en base 2 de la valeur de chaque pixel (un
nombre si limage est en niveaux de gris, 3 nombres si elle est en couleurs). Elle ncessite galement
de convertir le message insrer en une suite de 0 et de 1. Pour cela, nous pouvons par exemple
prendre la concatnation de la reprsentation en base 2 de chaque caractre ASCII.
An de garantir un minimum de scurit (mme si cet algorithme est trs facilement attaquable,
comme nous le verrons plus bas), la plupart des algorithmes de stganographie mlangent dabord
les lments du support, an de modier celui-ci de manire uniforme. Les gures 2 et 3, tires de
[6], illustrent ce principe : la gure 2 reprsente des modications sur le support (en noir) sans avoir
mlang celui-ci auparavant : on remarque une concentration des modications sur une zone du
support. La gure 3 reprsente dabord un mlange du support, puis des modications (en noir),
puis linverse du mlange eectu : on remarque une distribution uniforme des modications sur
tout le support.
La marche alatoire est initialise par la cl prive partage par lemetteur et le recepteur, de
faon ce que le rcepteur puisse extraire le message.
Fig. 2 Concentration des modications (en noir) lors dune insertion sans mlange du support
Fig. 3 Modications uniformments rparties lors dune insertion aprs mlange du support
Le principe de cet algorithme est de remplacer le bit de poids faible de chaque pixel (LSB :
Least Signicant Bit, bit le plus droite dans la reprsentation en base 2 dun nombre) par un bit
8
du symbole. La gure 4 illustre ce principe.
Lors de lextraction, le rcepteur naura alors plus qu initialiser la marche alatoire sur le sup-
port laide de la cl prive, et de rcuprer le LSB de chaque pixel pour reconstruire le message.
Fig. 4 Stganographie LSB sur une image en niveau de gris
3.1.2 Inconvnients, attaque
Le changement du LSB de chaque pixel entrainant une modication de +1 ou -1 sur celui-ci,
loeil humain ne voit alors pas la dirence entre une image normale et une image stganographie,
le systme semble sr face aux attaques. Cependant, les modications apportes entrainent un tel
changement dans la distribution du support quil est trs facilement attaquable.
Pourtant, premire vue, la distribution des LSB de limage et des lments du message tant
uniformes, les changements ne semblent alors pas modier grand chose. Cependant, si lon observe
maintenant lhistogramme de limage, on peut alors y remarquer une caractristique typique de ce
type dinsertion :
En eet, un changement de 1 sur chaque pixel va transformer un pixel de valeur 2i en un pixel
de valeur 2i +1. Inversement, un pixel de valeur 2i +1 deviendra un pixel de valeur 2i. Ainsi, dans
lhistogramme, les barres de chaque paire (2i, 2i + 1) auront tendance sgaliser.
En eet, si par exemple lhistogramme prsente 10 pixels dintensit 30, et 400 pixels dintensit
31, alors, comme chaque pixel a une chance sur deux dtre modi, environ 5 pixels dintensit
30 deviendront dintensit 31, et environ 200 pixels dintensit 31 deviendront dintensit 30. Nous
obtiendrons alors dans lhistogramme de limage stganographie environ le mme nombre de pixels
pour la valeur 30 et 31 : environ 205. La gure 5 illustre ce phnomne.
Nous pouvons donc voir que mme si limage stganographie ne parait pas modie, le chan-
gement dans la distribution des valeurs de pixels est si fort quune simple analyse statistique des
paires de valeurs permettent dattaquer le systme. Ce genre dattaque est le principe du test dit
du
2
.
3.2 Matrix embedding
3.2.1 Point de vue intuitif
Dans lexemple ci-dessus, la capacit dinsertion est de n : la taille du support. Etant donn
quun bit a une chance sur deux dtre modi, lecacit dinsertion est de 2 : nous pouvons ins-
9
Fig. 5 Partie de lhistogramme de limage de Lena avant insertion LSB ( gauche) et apres
insertion LSB ( droite) : les paires de valeurs sgalisent
rer deux bits en ne gnrant quune modication en moyenne. Cette ecacit peut cependant tre
augmente, si le message insrer est plus petit. En eet, observons lexemple suivant :
Soit deux bits b
1
, b
2
insrer laide de trois bits du support : x
1
, x
2
et x
3
. Soit a
1
= x
1
x
2
et a
2
= x
2
x
3
. An dinsrer nos deux bits, discernons les quatre cas suivants :
si a
1
= b
1
et a
2
= b
2
: pas de changements.
si a
1
= b
1
et a
2
= b
2
: changeons la valeur de x
1
.
si a
1
= b
1
et a
2
= b
2
: changeons la valeur de x
3
.
si a
1
= b
1
et a
2
= b
2
: changeons la valeur de x
2
.
Lors de lextraction, le recepteur naura alors qu calculer a
1
et a
2
qui seront les deux bits insrs.
Nous pouvons alors remarquer que pour insrer deux bits, la probabilit deectuer une modi-
cation sur le support est de
3
4
, alors quil tait de 1 pour la technique prcdente. Le prix payer
est que la capacit dinsertion est de
2n
3
, cest dire que la taille relative
2
du message par rapport
au support doit tre de
2
3
, alors quelle tait de 1 prcdemment.
La partie suivante explique quen fait, cette technique nest quun cas particulier dune autre,
appele matrix embedding, et que lecacit dinsertion peut encore tre augmente, si la taille
relative diminue.
3.2.2 Gnralisation
La technique de matrix embedding est une mthode de codage par syndrome, utilisant la thorie
des codes correcteurs, en particulier les codes linaires.
Codes correcteurs derreurs, codes linaires
Un code linaire est un code correcteur derreurs structur comme sous-espace vectoriel dun
corps ni. Ici, le corps utilis est le corps de Galois deux lments : F
2
= {0, 1}.
Un code linaire est dni par trois paramtres : [n, k, ], avec n > k, o des message de k bits
sont transmis comme des mots de n bits. reprsente la distance minimale entre chaque mot du
code. La distance utilise est la distance de Hamming, dnie par : d(x, y) =
n

i=1
x
i
y
i
pour tout
(x, y) F
n
2
F
n
2
. Nous dnissons de plus le poids de Hamming dun vecteur x par d(x, 0), cest
dire le nombre de 1 dans le vecteur.
2
La taille relative est dnie comme la longueur du message insrer divis par la taille du support disponible
10
Dans la thorie des codes correcteurs, deux entits souhaitent communiquer travers un canal
bruit. Pour cela, lemmeteur, qui dsire envoyer un message m F
k
2
, transforme celui-ci en un mot
de code c F
n
2
par :
c = Gm
avec G M
n,k
la matrice dite gnratrice du code linaire. Le rcepteur, qui reoit un mot c

F
n
2
,
calcule alors ce que lon appelle le syndrome du code, s F
nk
2
, par :
s = Hc

avec H M
nk,n
la matrice dite de parit du code. Remarquons que s F
nk
2
Si s = (0, ..., 0), alors c

= c et le message ne comporte pas derreur. Autrement, si s = (0, ..., 0),


alors le message comporte une ou plusieurs erreurs.
De plus, H tant une application de F
n
2
dans F
nk
2
, plusieurs codes peuvent avoir le mme
syndrome s. On note alors C(s) lensemble des codes ayant s comme syndrome. Cette ensemble
sappelle la classe (coset) de s, et est dni par : C(s) = {c F
n
2
: Hc = s}. On appelle alors chef
de classe (coset leader) llment de la classe qui a le poids de Hamming le plus faible.
Utilisation des codes linaires en stganographie : matrix embedding
Dans notre utilisation des codes linaires, le syndrome s reprsentera le message transmettre,
et les donnes traversant le canal, c

, seront le support. Lors de lextraction du message, le rcepteur


naura alors qu calculer le syndrome laide de la matrice H pour obtenir le message cach. La
dicult se trouve ici du ct de lemetteur.
En eet, le but est dinsrer un message m F
nk
2
dans un support x F
n
2
en le modiant le
moins possible. Pour cela, le principe de la technique est de modier x en y tel que
Hy = m (3)
Avec H M
nk,n
. Nous cherchons alors le vecteur e F
n
2
qui modie x en y, cest dire tel que
y = x + e (4)
Injectant lquation 4 dans 3, on obtient :
H(x + e) = m
He = mHx (5)
Le vecteur e recherch est donc un code ayant comme syndrome mHx. Etant donn que nous
cherchons modier le moins possible notre vecteur x, nous allons choisir le code ayant le poids
de Hamming le plus faible : le vecteur optimal est le chef de la classe C(m Hx). On montre en
fait que le nombre maximum de changement est infrieur au rayon de couverture R du code, car le
vecteur e aura un poids de Hamming infrieur R.
En gnral, la rsolution de lquation 5 est complique, et ncessite lutilisation du pivot de
Gauss, de complexit cubique sur le nombre de lignes de H (ici n-k). Cependant, lutilisation de bons
codes linaires peut simplier le problme, notamment avec des codes dont le rayon de couverture
est faible.
Exemple de matrix embedding : utilisation des codes de Hamming
Les codes de Hamming constituent une famille de codes linaires permettant la dtection et la
correction dune erreur si elle ne porte que sur un symbole du message. Leur distance minimale
est gale 3, et le rayon de couverture 1.
11
Ces codes sont paramtrs par un entier p : n = 2
p
1 et k = 2
p
1p. Les syndromes (donc les
messages dans le cas de la stganographie) sont donc de longueur n k = p. La matrice de parit
H M
p,2
p
1
est forme en plaant sur chaque colonne la reprsentation en binaire des entiers de 1
2
p
1.
Donc, si m Hx = He est un syndrome, alors (comme m Hx est de longueur p), il gure
dans une des colonnes de H. Ainsi, e sera le vecteur form dun 1 cette colonne, et de 0 ailleurs :
un seul changement est ncessaire pour transformer notre x en y ! Voici un exemple pour p = 3 :
Soit m = (1, 0, 1) le message insrer dans x = (0, 1, 1, 1, 0, 0, 1).
La matrice H utilise sera :
H =
_
_
0 0 0 1 1 1 1
0 1 1 0 0 1 1
1 0 1 0 1 0 1
_
_
Nous cherchons donc le vecteur e = (e
1
, e
2
, e
3
, e
4
, e
5
, e
6
, e
7
, ) tel que H(x + e) = m.
Pour cela, calculons mHx :
mHx =
_
_
1
0
1
_
_

_
_
0 0 0 1 1 1 1
0 1 1 0 0 1 1
1 0 1 0 1 0 1
_
_
_
_
_
_
_
_
_
_
_
_
0
1
1
1
0
0
1
_
_
_
_
_
_
_
_
_
_
=
_
_
1
0
1
_
_

_
_
0
1
0
_
_
=
_
_
1
1
1
_
_
On a donc He = (1, 1, 1) qui correspond la 7me ligne de H, do
e = (0, 0, 0, 0, 0, 0, 1)
Ainsi, le message transmis sera y = x + e = (0, 1, 1, 1, 0, 0, 0). Lors de lextraction, le recepteur na
alors plus qua calculer le syndrome :
Hy =
_
_
0 0 0 1 1 1 1
0 1 1 0 0 1 1
1 0 1 0 1 0 1
_
_
_
_
_
_
_
_
_
_
_
_
0
1
1
1
0
0
0
_
_
_
_
_
_
_
_
_
_
=
_
_
1
0
1
_
_
= m
Nous venons donc de voir que la technique de matrix embedding permet dinsrer p bits dans
un support de 2
p
1 bits en eectuant au maximum
3
un seul changement dans celui-ci. Si cela
parait premire vue trs ecace, remarquons quune image de 512x512 pixels comporte 262144
pixels, donc 262144 bits potentiels pour servir de support. Si lon veut appliquer la technique pr-
cdente, et neectuer quun seul changement dans limage, le message doit tre de longueur 17, car
3
En eet, la technique engendre soit 0 soit 1 changement
12
2
18
1 = 262143 > 262144. Cela reprsente une longueur relative de
17
262144
= 6, 48.10

5, ce qui est
peu.
Une technique possible pour palier cette faiblesse est de diviser le message en plusieurs parties,
et de drouler la mthode avec chaque morceau. Par exemple, pour p=3, la technique nous permet
dinsrer 3 bits dans un support de 7 bits, en neectuant au maximum quun seul changement.
Ainsi, si lon veut insrer 9 bits, il est ncessaire davoir un support de 2
9
= 512 bits. Cependant,
si lon coupe le message en 3, alors on peut eectuer 3 fois linsertion par matrice avec p = 3. Le
support doit alors tre de longueur 3 7 = 21 bits, et celui-ci subira 3 changements. La longueur
relative est maintenant de
9
21
0.4. Une technique LSB simple comme dcrite partie 3.1 aurait
engendre en moyenne 4.5 changements.
Cest de cette manire que sont implments la plupart des algorithmes de stganographie
utilisant la technique de matrix embedding, comme nous le verrons la partie 4 pour lalgorithme
F5.
3.2.3 Ecacit dinsertion
Nous allons maintenant nous intresser lecacit dinsertion de la technique de matrix em-
bedding. Lecacit dinsertion est dnie comme le nombre de bits pouvant tre insrs pour une
modication dans le support.
Lorsque nous insrons p bits, dans un support de 2
p
1 bits, nous eectuons 0 ou 1 changement
dans celui-ci. En eet, si m = Hx alors e = (0, ..., 0) ; le vecteur e reprsentant un nombre binaire
dans lintervalle [0, 2
p
1], ce cas a une probabilit de
1
2
p
. Inversement, nous changeons 1 bits dans
le support dans toutes les autres situations, donc avec une probabilit de 1
1
2
p
. Ainsi, le nombre
moyen de changements pour insrer p bits est de :
0
1
2
p
+ 1 (1
1
2
p
) = 1
1
2
p
= 1 2
p
Do le nombre de bits pouvant tre insrs pour 1 seul changement, i.e. lecacit dinsertion :
p
1 2
p
Dun autre ct, puisque nous insrons p bits dans 2
p
1 bits, la taille relative du message est
de :
p
2
p
1
La gure 6 (page 14) reprsente lvolution de lecacit dinsertion, tandis que la gure 7 (page
15) reprsente lvolution de la taille relative du message, toutes les deux en fonction du paramtre
p.
Choix du paramtre p
Nous pouvons donc voir que lecacit dinsertion ne dpend uniquement que du paramtre p
utilis. Dans la plupart des cas, comme expliqu la n du paragraphe prcdent, ce paramtre
nest pas directement gal la taille du message insrer. Ainsi, comment choisir ce paramtre
de manire optimale ? En fait, nous allons voir que celui-ci ne dpend uniquement que de la taille
relative du message insrer. En eet, nous devons dterminer le nombre de fois que nous allons
devoir diviser notre message an de linsrer. Soit K la longueur de notre message, N la longueur
de notre support, =
K
N
la taille relative du message et a le nombre de fois que lon va devoir
diviser ce dernier. Chaque changement engendrant une modication, nous devons choisir a le plus
petit possible. Celui-ci doit en fait vrier :
a(2
K
a
1) N < (a + 1)(2
K
a+1
1) (6)
13
Fig. 6 Evolution de lecacit dinsertion en fonction du paramtre p dans une technique de
matrix embedding utilisant les codes de Hamming.
En eet, L
a
= (2
K
a
1) est la longueur du support ncessaire pour un morceau de message de
longueur
K
a
, donc aL
a
est la longueur totale du support ncessaire. En divisant chaque membre de
lingalit 6 par a (a = 0) on obtient :
2
K
a
1
N
a
<
(a + 1)(2
K
a+1
1)
a

a
(a + 1)(2
K
a+1
1)
<
a
N

1
2
K
a
1

K
a
a
(a + 1)(2
K
a+1
1)
<
K
a
a
N

K
a
1
2
K
a
1

K
(a+1)
(2
K
a+1
1)
. .

a+1
<
K
a
2
K
a
1
. .

a
et
a+1
sont les tailles relatives pour une opration de matrix embedding avec respectivement
p =
K
a
et p =
K
a+1
.
Ainsi, le choix optimal pour le paramtre p se calcule partir de la taille relative du message.
Donc, lecacit dinsertion ne dpend elle aussi que de la taille relative de celui-ci.
3.3 Codes papier mouill
3.3.1 Introduction
Cette partie traite dune autre utilisation de la technique de matrix embedding, avec dautres
codes linaires. Cette autre utilisation est motive par une contrainte supplmentaire sur le schma
14
Fig. 7 Evolution de la taille relative en fonction du paramtre p dans une technique de matrix
embedding utilisant les codes de Hamming.
de stganographie : la rgle dite de slection non partage
4
, aussi appele criture sur papier mouill.
La technique dcrite ici est tire de J. Fridrich, M. Goljan, D. Soukal [7]. Le principe de cette pro-
blmatique, avant dexpliquer la mthaphore des codes papier mouill, suppose que lemetteur
du message ne souhaite pas utiliser tout le support disponible an de cacher son message. Cette
supposition est motive par le fait que celui-ci veut choisir les endroits du support modier, dans
un but de slectionner les parties de limage o les modications se feront le moins sentir. Cette
problmatique est appele rgle de slection. Elle peut tre partage par lemetteur et le rcepteur,
cependant, cela suppose alors que la rgle est la mme pour tous les supports utiliss, ou bien par-
tage avant chaque communication. Dans les deux cas cela pose un problme soit de scurit, soit
de performance. Ainsi, lorsque cette rgle de slection nest connue que de lemetteur, on appelle
cela criture sur papier mouill.
La mthaphore explique le fait que lemetteur voudrait cacher un message lintrieur dun
papier tant rest sous la pluie : celui-ci ne peut pas crire aux endroits mouills. Lors de la rcep-
tion, le papier ayant sch, la personne ne connait pas les endroits o a t cach le message, an
dextraire celui-ci ; do lide de rgle de slection non partage.
Le principe de ne pas pouvoir crire certains endroits dans le support entrane plus de scurit
et minimise encore plus les changements dans le support. Par exemple, dans lalgorithme F5 dA.
Westfeld, dcrit partie 4, le support utilis est la liste des coecients DCT aprs quantication
et arrondi. Comme rgle de slection, nous pourrions par exemple prendre les coecients faisant
perdre le plus dinformation lors de larrondi. En eet, un coecient DCT qui, aprs quantication,
est gal 3.47, va tre arrondi 3. Le fait quil soit choisi pour insrer le message, et donc modi
en 3 ou en 4 ne changera pas grand chose au rsultat, car au lieu de perdre 0.47 cause de la
compression JPEG, il perdrait soit 0.47 soit 0.53 cause de linsertion. Si lon ne le discerne pas des
autres, il pourra alors tre chang en 2 si lopration de matrix embedding dcide de le changer, ce
qui entraine une plus grosse modication. Cet exemple de mode de slection pourrait alors cacher
les modications engendres par linsertion dans les modication dues une compression JPEG.
4
non-shared selection rule
15
3.3.2 Description
La technique dcrite ici utilise galement des codes linaires. Cependant, dans notre support x
F
n
2
, nous supposons ne pouvoir modier que k dentre eux : les x
j
, j J {1, ..., n}, avec |J| = k.
Ainsi, les (n-k) bits x
i
, i / J ne peuvent pas tre modis.
Utilisant la technique de matrix embedding, an de cacher un message m F
m
2
, lemetteur doit
modier x en y de telle sorte que :
Dy = m (7)
Avec D M
m,n
la matrice de parit dun code linaire, pouvant tre retrouve par lemetteur.
Dcomposons le vecteur y en y = x + v, o v est le vecteur des modications apportes x.
Lquation 7 devient donc :
Dv = mDx (8)
De plus, la rgle de slection implique v
j
= 0, j J, do y
j
= x
j
, j J. Ainsi, les inconnues
de lquation 8 sont au nombre de k : nous pouvons donc laguer notre systme, et enlever les (nk)
colonnes de D, et les (n k) lignes de v, correspondants aux indices j / J (les (n k) colonnes
enleves de D sont quelcquonques et ne nous interessent pas, puisque elles seront multiplies par les
0 de v). En notant u le vecteur obtenu partir de v, z le vecteur mDx, et H la matrice obtenue
partir de D, nous obtenons lquation suivante :
Hu = z (9)
qui est un systme k inconnues : u F
k
2
, et o H M
m,k
et z F
m
2
. Ainsi, trouver D revient
trouver H, et le problme rsoudre est le mme qu lquation 5 page 11, le vecteur u est le
chef de classe de C(z), dont le poids de Hamming est infrieur au rayon de couverture R du code.
Cependant, on note une dirence, et non des moindres. En eet, dans le problme prcdent, nous
imposions H dtre la matrice de parit dun code linaire (code de Hamming par exemple) connu
de lemetteur et du rcepteur, or ici, H est une sous-matrice de D, qui dpend de J, et donc du
support. Ainsi, pour deux supports dirents, J sera la plupart du temps dirent, et donc H ga-
lement. Une solution est de prendre pour D la matrice de parit dun code linaire quelcquonque,
et de rsoudre le systme laide du pivot de Gauss.
En eet, mme pour les codes de Hamming vus prcdemment, la technique ne marche plus.
Lexemple suivant le montre :
Soit m = (1, 0, 1) le message insrer dans x = (1, 0, 0, 0, 0, 0, 1), et soit J = {1, 2, 5, 6, 7}, cest
dire que les bits n3 et 4 ne peuvent pas tre modis. Alors on a, si lon suit la mthode dcrite
partie 3.2.2 page 11 :
He = mHx =
_
_
1
0
1
_
_

_
_
0 0 0 1 1 1 1
0 1 1 0 0 1 1
1 0 1 0 1 0 1
_
_
_
_
_
_
_
_
_
_
_
_
1
0
0
0
0
0
1
_
_
_
_
_
_
_
_
_
_
=
_
_
1
0
1
_
_

_
_
1
1
0
_
_
=
_
_
0
1
1
_
_
Sans la rgle de slection, la solution est evidemment e = (0, 0, 1, 0, 0, 0, 0) puisque mHx est la
3me colonne de H. Mais puisque nous ne pouvons pas modier les bits n3 et 4, on a e
3
= e
4
= 0,
16
et on peut enlever les colonnes 3 et 4 de H. Do le systme rsoudre :
_
_
0 0 1 1 1
0 1 0 1 1
1 0 1 0 1
_
_
_
_
_
_
_
_
e
1
e
2
e
5
e
6
e
7
_
_
_
_
_
_
=
_
_
0
1
1
_
_
qui est un systme classique 5 inconnues, rsolvable avec les techniques de combinaisons et sub-
stitutions, et dont la solution est e = (1, 1, 0, 0, 0). La rsolution de ce type de systmes est de
complexit cubique sur le nombre dquations, donc viter en pratique. [7] propose alors de
prendre comme matrice D un certain type de matrices creuses alatoires, entranant une complexit
moindre pour rsoudre le systme.
En eet, supposons que notre matrice D a une distribution telle que lon puisse y appliquer la
mthode suivante :
Prendre une colonne comportant exactement un 1, se trouvant la i
me
1
ligne. Permuter cette
colonne avec la premire colonne de la matrice, et la i
me
1
ligne avec la premire ligne de la
matrice.
Dans la matrice prive de la premire colonne et de la premire ligne, prendre une colonne
comportant exactement un 1, se trouvant la i
me
2
ligne. Permuter cette colonne avec la
deuxime colonne de la matrice, et la i
me
2
ligne avec la deuxime ligne de la matrice.
Rpter ces oprations avec la matrice prive des deux premires colonnes et des deux premire
lignes, et continuer le processus jusqu la n de la matrice.
Ainsi, la matrice permute obtenue est triangulaire suprieure, et la rsolution se fait en cas-
cade en partant de la dernire ligne, ne comportant quun coecient. Ce processus est appel LT
Process, et est tir des codes correcteurs appels LT Codes. Si un moment donn, on ne trouve
pas de colonne avec un seul 1 lintrieur, alors le processus choue.
Les auteurs montrent que pour que les matrices puissent tre utilises dans ce processus, il faut
que le poids de Hamming de leurs colonnes suivent une distribution de probabilit dite RSD, cest
dire :
La probabilit quune colonne de D ait un poids de Hamming i, 1 i k est
[i]+[i]

, o :
[i] =
_
1
m
si i = 1
1
i(i1)
sinon.
et :
[i] =
_
_
_
R
im
si i = 1, .., m/R 1
Rln(R/)
m
si i = m/R
0 si i = m/R + 1, .., m
et :
=
m

i=1
([i] + [i])
et :
R = cln(m/)

m
Avec et c des constantes bien choisies.
17
An dappliquer ceci, lemetteur peut par exemple gnrer partir de la cl secrte une suite
de nombre suivant la distribution prcdente, les paramtres et c pouvant tre publics. Il peut
alors rsoudre facilement le systme prcdent, et dterminer les changements eectuer. Lors
de lextraction, le rcepteur disposera alors de la mme matrice D que lemetteur, et calculera
simplement le syndrome comme dans un schma de matrix embedding classique. Notons quici
aussi, un paramtre spcique doit ncessairement tre transmis : la taille du message. Comme avec
les codes de Hamming, o cela concernait le paramtre p de lalgorithme, celui-ci peut par exemple
tre introduit dans les premiers bits du support.
18
4 Lalgorithme F5
4.1 Introduction
Lalgorithme F5 est probablement la premire implmentation pratique dune technique de ma-
trix embedding en stganographie. Il a t invent par A. Westfeld, et prsent en 1999 [6]. Le nom
provient des prcdents algorithmes dvelopps par lauteur : F3 et F4.
F5 insre le message pendant une compression JPEG, et utilise les LSB des coecients DCT pour
raliser lopration de matrix embedding. Lalgorithme est sr face aux attaques visuelles et statis-
tiques car il sadapte la distribution spciques des coecients DCT.
Dans un premier temps, nous dcrirons brivement lalgorithme de compression JPEG, puis nous
verrons ensuite en dtail le fonctionnement de lalgorithme. Ensuite, nous observerons quelques
rsultats exprimentaux obtenus aprs une implmentation de F5. Enn, nous expliquerons une
attaque de lalgorithme ralise par J. Fridrich, M. Goljan, et D. Hogea [3], et prsenterons l aussi
quelques rsultats exprimentaux de limplmentation de cette attaque.
4.2 Compression JPEG
JPEG est lacronyme de Joint Photographic Expert Group, qui est le nom de lorganisation qui
cra la norme JPEG. Cest aussi le nom du fameux algorithme de compression des images. Cest
une mthode avec perte, engendrant des taux de compression de 3 100, selon le facteur de qualit
exig.
Il se dcompose en six tapes :
Dcoupage en blocs de pixels
Passage du mode RGB au mode YCbCr.
Sous-echantillonnage sur les composantes de chrominance.
Application de la Transformation en Cosinus Discrete (DCT).
Quantication de chaque bloc par une matrice de quantication.
Codage RLE et Human.
Dcoupage en blocs de pixels Limage est gnralement dcoupe en blocs de 64 (8x8) pixels.
Cette taille de blocs prcise est celle qui apporte les meilleurs rsultats lors de la compression.
Passage du mode RGC au mode YCbCr Chaque bloc de limage, comportant trois compo-
santes : rouge, vert et bleu, est transform en un bloc de trois composantes : Y (luminance), Cb
(chrominance bleue) et Cr (chrominance rouge) par une opration matricielle.
Sous-echantillonnage sur les composantes de chrominance Loeil humain tant plus sen-
sible la luminance quaux chrominances, celles-ci sont sous chantillonnes : une moyenne est
faite sur chaque bloc de 4x4 pixels. Le gain est ainsi de 50%, et loeil humain ne peroit pas la
dirence sur des images photographiques. En revanche le rsultat est plutt mauvais sur du texte
par exemple.
Application de la Transformation en Cosinus Discrete (DCT) La Transforme en Cosinus
Discrete est en fait la partie relle de la transforme de Fourier discrete. Celle-ci permet de passer
du domaine dit spatial au domaine frquentiel. Cette transformation seectue selon la formule
suivante :
S
u,v
=
1
4
C(u)C(v)
7

x=0
7

y=0
s
xy
cos
(2x + 1)u
16
cos
(2y + 1)v
16
avec
C(0) =
1

2
et C(u) = 1 si u = 0
s
xy
reprsentant les valeurs des pixels dans le domaine spatial, et S
u,v
les valeurs des coecients
DCT.
19
Cette opration permet une reprsentation frquentielle de limage, les coecients basses fr-
quences (correspondants un changement long dintensit) sont rangs dans le coin suprieur gauche
du bloc, et les coecients hautes frquences (correspondants un changement rapide dintensit)
sont rangs dans le coin infrieur droit du bloc. En eet, pour (u, v) = (0, 0), nous observons que le
coecient plac dans le coin suprieur gauche reprsente la moyenne
5
des intensits dans limage ;
ce coecient est appel coecient DC, alors que tous les autres sont appels AC.
Loeil humain tant plus sensible aux basses quaux hautes frquences, nous allons pouvoir
eectuer une perte au niveau de ces derniers. La gure 8 reprsente le passage du domaine spatial
au domaine frquentiel laide de la DCT sur un bloc de pixels cods sur 8 bits (valeur entre 0 et
255).
Fig. 8 Evolution dun bloc de pixel lors une Transformation en Cosinus Discrete
Quantication de chaque bloc par une matrice de quantication La DCT ayant t ef-
fectue sur les blocs de chaque composante, lalgorithme de compression va alors quantier ces
coecients partir dune matrice, dpendant dun facteur de qualit donn par lutilisateur (gn-
ralement entre 0 et 100), puis arrondir ces coecients lentier le plus proche. Cest lors de cette
tape que la perte dinformation est la plus importante.
Cette matrice (il y en a en fait une pour la composante de luminance, et une pour les deux
composantes de chrominance) comporte des coecients se rapprochant de 10 dans le coin suprieur
gauche, et se rapprochant de 100 sur le coin infrieur droit, ces nombres augmentant si le facteur
de qualit est bas. Ainsi, lors de la quantication (division terme terme des blocs de limage par
la matrice de quantication), les coecients les plus altrs seront ceux correspondant aux hautes
frquences, une majorit dentre eux seront dailleurs transforms en zro. La gure 9 reprsente
un bloc de coecients DCT de la composante de luminance aprs quantication.
Fig. 9 Bloc de coecients DCT de luminance aprs une quantication
Les histogrammes des coecients DCT dune image aprs compression jpeg comportent des
caractristiques remarquables, comme on peut le voir dans la gure 10 : les coecients les plus
5
multiplie par 4 : on ne divise que par 4
20
importants sont ceux gaux 0, et on observe une symtrie par rapport la valeur 0. De plus,
les histogrammes des images naturelles prsentent plus de coecients non nuls impairs que pairs
(hormis 0).
Fig. 10 Histogramme des coecients DCT dune image naturelle
Codage RLE et Human Les algorithmes de compression RLE et Human sont des algorithmes
sans perte. Ils utilisent les statistiques des coecients DCT et leur corrlation an de minimiser le
cot de codage de limage.
Le codage RLE permet de coder les plages de coecients identiques par un seul symbole. Si lon
parcourt les blocs obtenus aprs la quantication sous forme de zig-zag, on peut facilement voir
apparaitre des plages de zros. Le codage RLE permet alors de gagner de la place.
Le codage de Human utilise la probabilit doccurence de chaque coecient an de coder ceux
qui aparaissent le plus souvent part des symboles courts, et de coder ceux qui aparaissent le moins
souvent par des symboles plus longs, chaque symbole ne devant pas tre le dbut dun autre. Cette
mthode permet dapprocher lentropie de la source en cot de codage par coecient.
4.3 Description de lalgorithme
Lalgorithme F5 dA. Westfeld est un algorithme 1 sur les coecients DCT quantis non
nuls dune image (pendant une compression JPEG), en utilisant la technique de matrix embedding.
An dtre sr face aux attaques statistiques, il prserve les caractristiques de lhistogramme des
coecients DCT dune image naturelle : lors dun changement de valeur dun bit, lalgorithme d-
crmente la valeur absolue du coecient (il ny a alors plus dgalisation des paires de valeurs
comme dans un LSB classique). Le seul artfact produit est une augmentation du nombre de co-
ecients 0, cependant, cette caractristique ressemblera simplement une compression JPEG
avec un facteur de qualit infrieur. De plus, pour prserver la symtrie de limage, les coecients
positifs impairs et ngatifs pairs ont un LSB de valeur 1, alors que les coecients ngatifs impairs
et positifs pairs ont un LSB de valeur 0.
Lalgorithme prsent par A. Westfeld prend 5 paramtres en entre pour insrer un message :
une image servant de support (compresse ou non).
un message tre insr.
le facteur de qualit tre utilis lors de la quantication.
un mot de passe an de gnrer une marche alatoire sur le support et le message.
un commentaire pouvant tre insr dans len-tte du chier JPEG.
21
Il prend deux paramtres en entre an dextraire un message :
une image stganographie.
le mot de passe utilis lors de linsertion.
Voici le fonctionnement de lalgorithme dinsertion :
1. Eectuer une compression JPEG de limage, arrter juste aprs la quantication.
2. Calculer la capacit C de limage et en dduire le paramtre p pour eectuer la technique de
matrix embedding.
3. Gnrer une marche pseudo-alatoire an de mlanger le support et le message.
4. Insrer dans les premiers bits du support la taille du paramtre p utilis ainsi que la taille du
message, en utilisant simplement une technique LSB.
5. Insrer des morceaux de message de longueur p dans des morceaux de support (coecients AC
non nul) de longueur 2
p
1 en utilisant la technique de matrix embedding. An de changer la
valeur dun bit, la valeur absolue du coecient est dcrmente de 1. Si le coecient devient
0, cette situation est appele eondrement, et les p bits devant tre insrs sont insrs
nouveau en retournant ltape 5.
6. Si tout le message a pu tre insr, alors le processus a russi. Sinon, un warning est ach.
Lors de lextraction, le rcepteur na alors plus qua gnrer la marche alatoire, retrouver les
paramtres de lalgorithme utiliss, et de calculer le syndrome de chaque bloc de coecients AC
non nuls an de reconstruire le message.
La capacit C calculer lors de ltape 2 est gale :
C =
nombre de coef DCT
..
h
DCT

nombre de coef DC
..
h
DCT
64

coef 0
..
h(0)
coef perdus par eondrement
..
h(1) + 0.49h(1)
4.4 Attaque de lalgorithme F5
Lattaque de lalgorithme F5 a t prsent en 2002 par J. Fridrich, M. Goljan, D. Hogea [3].
Lattaque est base sur le fait de pouvoir reconstruire une estimation de lhistogramme de limage
juste avant linsertion du message. Ensuite, une analyse des dirences entre cette estimation et
limage intercepte permet den dduire une approximation de la probabilit de modication dun
coecient, et donc de la taille du message insr.
Lattaque se prsente donc en deux points :
estimer lhistogramme de limage avant insertion des donnes.
dduire de cet histogramme la longueur du message insr.
Estimation de lhistogramme de limage avant insertion des donnes
An de construire lestimation de lhistogramme de limage intercepte avant insertion, limage
est dcompresse dans le domaine spatial, dcale de 4 pixels dans les deux directions (horizon-
talement et verticalement), puis recompresse en utilisant le mme facteur de qualit que lors de
linsertion. Ce dcalage permet de casser la structure des blocs des coecients DCT, an dobtenir
une approximation de leur valeur avant la quantication. En outre, un ltre passe-bas est appliqu
juste aprs le dcalage, et ce an dattnuer les eets de blocs dus la quantication.
Estimation de la longueur du message insr
22
An destimer la longueur du message insr, les auteurs calculent dabord la probabilit quun
coecient AC non nul soit modi.
Soit H, h,

h les histogrammes respectifs de limage stganographie, limage avant insertion de


donnes, et lestimation de cette derniere. H(i) reprsentera par exemple le nombre de coecients
de limage stganographi dont la valeur absolue est gale i. De plus, pour un histogramme X
de coecients DCT, nous noterons X
k,l
, 1 k, l 8, lhistogramme des coecients se trouvant
la place (k, l) dans le bloc 8x8 (par exemple H
0,0
est lhistogramme des coecients DC de limage
stganographie)
Alors, nous avons les quations suivantes, pour 1 k, l 8 :
H
k,l
(d) =
_
h
k,l
(d + 1) + (1 )h
k,l
(d) si d = 0,
h
k,l
(1) + h
k,l
(0) si d = 0.
(10)
En eet, avec une probabilit , un coecient de valeur aboslue d + 1 sera transorm en un
coecient de valeur absolue d, et avec une probabilit (1 ), ce coecient ne sera pas modi.
Etant donn que nous avons une estimation

h de h, nous pouvons calculer

H : lhistogramme de
limage stganographie partir de lestimation obtenue de lhistogramme de limage, en appliquant
lquation 10 pour h =

h :

H
k,l
(d) =
_

h
k,l
(d + 1) + (1 )

h
k,l
(d) si d = 0,

h
k,l
(1) +

h
k,l
(0) si d = 0.
Ainsi, nous cherchons qui va minimiser les dirences entre lhistogramme estim

H et celui
intercept H. Pour cela, les auteurs utilisent la mthode des moindres carrs. De plus, les calculs ne
sont raliss que pour d = 0 et d = 1, ces deux valeurs tant les plus touches dans linsertion par
lalgorithme F5. En outre, tant donn que nous avons 8x8 rsultats possibles pour (un rsultat
pour chaque couple (h, k)), les auteurs choisissent de prendre la moyenne des rsultats obtenus pour
les cases (2, 1), (1, 2), (2, 2), correspondant aux coecients AC des basses frquences. Ceci sexplique
par le fait que le dcalage de 4 pixels des deux cts engendre des discontinuits au milieu de chaque
bloc ( cause de leet bloc de la compression JPEG), donc des hautes frquences non voulues.
Lapproximation par les moindres carrs donne la formule suivante pour les
k,l
:

k,l
=

h
k,l
(1)[H
k,l
(0)

h
k,l
(0)] + [H
k,l
(1)

h
k,l
(1)][

h
k,l
(2)

h
k,l
(1)]

h
2
k,l
(1) + [

h
k,l
(2)

h
k,l
(1)]
2
et :
=

2,1
+
1,2
+
2,2
3
A partir de (la probabilit de changement dun coecient AC non nul), nous pouvons obtenir
la taille du message insr.
En eet, si M est la longueur du message, on a :
M = Ecacit dinsertion Nombre de changements par matrix embedding
Lecacit dinsertion tant le nombre de bits pouvant tre insrs avec un seul changement, il
est gal p
2
p
2
p
1
(cf 3.2.3).
Le nombre de changements par matrix embedding m se calcule de la manire suivante :
Si n est le nombre total de changements, s le nombre de changements cause des eondrements,
P le nombre total de coecients AC non nuls, et P
s
la probabilit quun coecient entraine un
eondrement, on a :
P
s
=
h(1)
P
, donc s = nP
s
.
De plus, on a n = m + s m = n(1 P
s
) m = n(1
h(1)
P
).
23
Et enn, n = P.
Do la formule pour M :
M =
2
p
2
p
1
p(P h(1))
4.5 Implmentations
Durant ce projet, jai t amen implmenter certains algorithmes, et donc dvelopper 4
excutables :
compress : pour simuler une compression jpeg.
embed : pour insrer un message dans une image en utilisant lalgorithme F5 dA. Westfeld.
extract : pour extraire un message insr avec le prcedent excutable.
attack : une implmentation de lattaque de lalgorithme F5.
Ces programmes ont t crits en langage C++, car cest un langage rapide, avec beaucoup
de possibilits, et o je possdais galement quelques sources, notamment pour le traitement des
images. Ils fonctionnent sous GNU/Linux et un makele est fourni pour compiler le tout. La gure
11 illustre lespace de travail des programmes crits.
Fig. 11 Architecture de lespace de travail des programmes crits. En bleu sont reprsents les
dossiers, en rouge les programmes, en vert les codes sources, et en noir les autres chiers.
Le format de chier JPEG tant plutt complexe matriser, et celui-ci ntant pas le sujet
principal du projet, jai d contourner ce problme en stockant les donnes sous forme dune liste
de coecients DCT, dans un chier avec extension .jpegLike. Lorsque le besoin dacher ces
images se ressentait, il tait alors ncessaire de les dcompresser an de les restituer dans leur
format dorigine : .pgm.
4.6 Implmentation et rsultats de lalgorithme F5
An dimplmenter lalgorithme F5 vu partie 4, deux classes ont t cres : Embedding pour
linsertion, et Extraction pour lextraction. La modlisation UML de ces classes est reprsente
24
gure 12.
Le programme principal pour linsertion est le chier mainEmbed.cpp. Il gnre un excutable
embed dont lusage est le suivant :
./embed [imageIn] [imageOut] [message] [password] [qualityFactor]
O :
imageIn est le chemin de limage servant de support.
imageOut est le chemin de limage gnre en sortie.
message est le chemin du chier contenant le message.
password est le mot de passe ncessaire.
qualityFactor est le facteur de qualit requis lors de la compression jpeg.
Par exemple :
./embed images/originales/lena.pgm images/stego/lena.pgm message.txt 007 80
Fig. 12 Diagramme de classe des classes Embedding et Extraction
En sortie, le programme gnre un chier .pgm et un chier.jpegLike portant le nom de limage
de sortie, qui elle est limage stganographie dcomprsse an de voir le rsultat.
25
Le programme principal pour lextraction est le chier mainExtract.cpp. Il gnre un excutable
extract dont lusage est le suivant :
./extract [imageIn] [password]
O :
imageIn est limage stganographie dcompresse
password est le mot de passe ncessaire.
NB : Limage dcompresse au format pgm doit tre accompagne (dans le mme dossier) du chier
.jpegLike compresse.
Par exemple :
./extract images/stego/lena.pgm 007
Le programme ne gnre rien en sortie, il se contente dacher le message extrait.
Ces deux programmes utilisent la classe DCTCoef qui est une structure permettant de stocker
une suite de coecients DCT (cf gure 12 pour le diagramme UML). La structure Message est en
fait un vector<int>.
Rsultats
La gure 13 prsente limage Goldhill.pgm aprs une simple compression (facteur de qualit 70),
et aprs une compression puis insertion dun message de 10 kbits, ce qui reprsente environ 25%
de la capacit du support. On remarque que le changement nest pas perceptible pour loeil humain.
La gure 14 reprsente la dirence des histogrammes des coecients DCT des deux images
prcdentes. Malgrs un fort pic au niveau des coecients 0, cela reste convenable car le nombre
de dirences est denviron 2000, ce qui ne reprsente pas grand chose sur les 512x512 = 262144
coecients de limage.
26
Fig. 13 image goldhill aprs une compression simple (a) et aprs insertion dun message (b).
Fig. 14 Dirence des histogrammes des deux images prcdentes.
4.7 Implmentation et rsultats de lattaque de lalgorithme F5
Lattaque de lalgorithme F5 est implmente dans le chier attack.cpp et gnre un excutable
attack dont lusage est le suivant :
./attack [imageIn] [qualityFactor]
O
imageIn est limage stganographie dcompresse
27
qualityFactor est le facteur de qualit utilis lors de linsertion.
Par exemple :
./attack images/stego/lena.pgm 80
Lattaque a t teste sur plusieurs images pgm en niveaux de gris, de rsolution 512x512, avec
un facteur de qualit entre 80 et 90. Le tableau 15 rcapitule les rsultats, en mettant en parallle
les valeurs de et la longueur du message insr obtenus lors de linsertion, et ceux obtenus aprs
estimation.
Image

n n
baboon 0.11 0.12 33456 30831
goldhill 0.26 0.24 33744 30847
house 0.16 0.16 5648 5597
lena 0 0.03 0 8755
sailboat 0.29 0.17 45072 34341
tiany 0 -0.002 0 0
Fig. 15 Rsultats obtenus pour lattaque de lalgorithme F5 sur direntes images.
28
5 Conclusion
En conclusion, nous avons pu voir que la construction dun schma de stganographie ntait
pas une chose aise, avec la ncessit de modier peu et surtout dune bonne manire le support,
an de cacher lexistence dun message. Nous avons galement pu voir que lutilisation des codes
correcteurs en stganographie, et notemment des codes linaires, tait un bon moyen de rduire le
nombre de changements eectus dans un support, et pouvait sadapter la rgle de slection non
partage. Dautre part, les images JPEG, avec la liste des coecients DCT comme support, sont
beaucoup utilises en stganographie, du fait du nombre important dchanges dimages sous ce for-
mat. Ainsi, un bon algorithme de stganographie se doit de prserver les statistiques des coecients
DCT. Lalgorithme F5 est un bon exemple de combinaison des techniques de matrix embedding et
de prservation de lhistogramme de limage. Cependant, il entrane certaines modications spci-
ques, utilises pour lattaque de celui-ci.
Une amlioration possible des schmas de stganographie rside dans la robustesse que lon peut
y apporter : garder le message insr intact aprs altration de limage par un attaquant : com-
pression, redimensionnement, ...etc. Cette robustesse est inexistante dans les schmas vus dans ce
projet, ceux-ci utilisant les LSB des coecients DCT, ils sont extrmement sensibles la moindre
modication.
Enn, ce projet a t me concernant quelque chose de positif, qui ma permis dapprendre des
choses intressantes, notemment sur la thorie de linformation, les codes correcteurs, la compression
jpeg, et le traitement des images, o jai pu approfondir et poursuivre certaines notions vues dans
mon cursus. Jai galement t confront ltude darticles de recherche plutt rcents, et la
rdaction de documents avec L
A
T
E
X, ce qui est un plus concernant mon projet professionnel qui est
la recherche informatique.
29
6 Rfrences bibliographiques
Rfrences
[1] J. Barbier : Analyse de canneaux de communication dans un contexte non coopratif, 2007
134-172.
[2] I.J. Cox, M.L. Miller, J.A. Bloom, J. Fridrich, T. Kalker : Digital Watermarking and Stegano-
graphy (second edition) 425-467.
[3] J. Fridrich, M. Goljan, D. Hogea : Steganalysis of JPEG Images : Breaking the F5 Algorithm.
[4] C. Cachin, An Information-Theoretic Model for Steganography.
[5] J. Fridrich, P. Lisonek, D. Soukal : On Steganographic Embedding Eciency.
[6] A. Westfeld : F5 - A Steganographic Algorithm. High Capacity Despite Better Steganalysis,
1999.
[7] J. Fridrich, M. Goljan, D. Soukal : Ecient Wet Paper Codes.
[8] http ://www.w3.org/Graphics/JPEG/itu-t81.pdf.
30
A Fichiers source
A.1 DCTCoef.h
/
Name : DCTCoef
aut hor : R mi Watri gant
dat e : 04/05/09
de s c r i pt i on : Cl asse cont enant l e s c o e f f i c i e n t s DCT q u a n t i f i s d une image ( i nt e g e r s )

/
#i f ndef DCTCoef_H
#define DCTCoef_H
#include <vector >
#include <i ostream>
using namespace st d ;
cl ass DCTCoef {
private :
vector <int> AC; // l i s t e des coef AC
vector <int> DC; // l i s t e des coef DC
/
l s b
ret ourne l e l s b d un e nt i e r
\param n l e nt i e r

/
i nt l s b ( i nt n ) ;
public :
/
DCTCoef
cons t r uct eur par d f a u t

/
DCTCoef ( ) ;
/
DCTCoef
cons t r uct eur par val eur
\param AC vect eur des coef AC
\param DC vect eur des coef DC

/
DCTCoef ( vector <int> AC, vector <int> DC) ;
/
31

acces s eur vect eur AC

/
vector <int> getAC ( ) ;
/

acces s eur vect eur DC

/
vector <int> getDC ( ) ;
/

mutateur vect eur AC


\param AC l e vect eur des coef AC

/
void setAC( vector <int> AC) ;
/

mutateur vect eur DC


\param DC l e vect eur des coef DC

/
void setDC( vector <int> DC) ;
/

getNextNonZeroAC
ret ourne l e prochai n coef ac non nul
\param i l i ndi c e p a r t i r d o l on recherche

/
i nt getNextNonZeroAC( i nt i ) ;
/

getNextNonZeroAC
ret ourne l i ndi c e du prochai n coef ac non nul
\param i l i ndi c e p a r t i r d o l on recherche

/
i nt getIthNextNonZeroAC( i nt i ) ;
/

getNbDC
ret ourne l e nombre de c o e f f i c i e n t s DC

/
i nt getNbDC( ) ;
/
32

getNbAC
ret ourne l e nombre de coef AC

/
i nt getNbAC( ) ;
/

getNbCoef
ret ourne l e nombre de coef

/
i nt getNbCoef ( ) ;
/

getNbACEqualsTo
ret ourne l e nombre de c o e f f i c i e n t s AC gaux l a v al e ur abs ol ue de v al
\param v al val eur t e s t e r

/
i nt getNbACEqualsTo ( i nt val ) ;
/

getIthAC
ret ourne l e ieme coef AC
\param i i ndi c e du coef r et our ner

/
i nt getIthAC( i nt i ) ;
/

set It hAC
modi f i e l e ieme coef AC
\param i l i ndi c e du coef a modi f i er
\param v al l a val e ur met t re l a pl ace

/
void setIthAC( i nt i , i nt val ) ;
/

setIthACLSB
modi f i e l e l s b de ieme coef AC
\param i l i ndi c e du coef a modi f i er
\param v al l a val e ur du l s b met t re l a pl ace

/
void setIthACLSB( i nt i , i nt val ) ;
/

getIthDC
33
ret ourne l e ieme coef DC
\param i l i ndex du coef DC que l on recherche

/
i nt getIthDC( i nt i ) ;
};
#endif
34
A.2 DCTCoef.cpp
/
Name : DCTCoef
aut hor : R mi Watri gant
dat e : 04/05/09
de s c r i pt i on : Cl asse cont enant l e s c o e f f i c i e n t s DCT q u a n t i f i s d une image ( i nt e g e r s )

/
#include "DCTCoef . h"
#include <c s t dl i b >
#include <stdexcept >
#include <math . h>
/
DCTCoef
cons t r uct eur par d f a u t

/
DCTCoef : : DCTCoef ( ) {
}
/
DCTCoef
cons t r uct eur par val eur
\param AC vect eur des coef AC
\param DC vect eur des coef DC

/
DCTCoef : : DCTCoef ( vector <int> AC, vector <int> DC) {
for ( i nt i = 0 ; i < AC. s i z e ( ) ; i ++)
{
( this>AC) . push_back (AC[ i ] ) ;
}
for ( i nt i = 0 ; i < DC. s i z e ( ) ; i ++)
{
( this>DC) . push_back (DC[ i ] ) ;
}
}
/

acces s eur vect eur AC

/
vector <int> DCTCoef : : getAC( ) {
return AC;
}
35
/

acces s eur vect eur DC

/
vector <int> DCTCoef : : getDC( ) {
return DC;
}
/

mutateur vect eur AC


\param AC l e vect eur des coef AC

/
void DCTCoef : : setAC( vector <int> AC) {
( this>AC) . c l e a r ( ) ;
for ( i nt i = 0 ; i < AC. s i z e ( ) ; i ++)
{
( this>AC) . push_back (AC[ i ] ) ;
}
}
/

mutateur vect eur DC


\param DC l e vect eur des coef DC

/
void DCTCoef : : setDC( vector <int> DC) {
( this>DC) . c l e a r ( ) ;
for ( i nt i = 0 ; i < DC. s i z e ( ) ; i ++)
{
( this>DC) . push_back (DC[ i ] ) ;
}
}
/

getNextNonZeroAC
ret ourne l e prochai n coef ac non nul
\param depart l i ndi c e p a r t i r d o l on recherche

/
i nt DCTCoef : : getNextNonZeroAC( i nt depart ) {
i f ( ( depart <0) | | ( depart>=AC. s i z e ( ) ) )
{
// envoi e d except i on
cout << " i=" << depart << endl ;
throw std : : l engt h_er r or ( "DCTCoef : : getNextNonZeroAC : i ndi c e non val i de " ) ;
36
e xi t ( 1);
}
i nt i = depart ;
do
{
i ++;
i f ( i >= AC. s i z e ( ) )
{
// envoi e d except i on
throw std : : over f l ow_er r or ( "DCTCoef : : getNextNonZeroAC : d bor de me nt " ) ;
}
}while (AC[ i ] == 0 ) ;
return AC[ i ] ;
}
/

getNextNonZeroAC
ret ourne l i ndi c e du prochai n coef ac non nul
\param depart l i ndi c e p a r t i r d o l on recherche

/
i nt DCTCoef : : getIthNextNonZeroAC( i nt depart ) {
i f ( ( depart <0) | | ( depart>=AC. s i z e ( ) ) )
{
// envoi e d except i on
cout << " i=" << depart << endl ;
throw std : : l engt h_er r or ( "DCTCoef : : getNextNonZeroAC : i ndi c e non val i de " ) ;
}
i nt i = depart ;
do
{
i ++;
i f ( i >= AC. s i z e ( ) )
{
// envoi e d except i on
throw std : : over f l ow_er r or ( "DCTCoef : : getNextNonZeroAC : d bor de me nt " ) ;
}
}while (AC[ i ] == 0 ) ;
return i ;
}
/

37
getNbDC
ret ourne l e nombre de c o e f f i c i e n t s DC

/
i nt DCTCoef : : getNbDC( ) {
return DC. s i z e ( ) ;
}
/

getNbAC
ret ourne l e nombre de coef AC

/
i nt DCTCoef : : getNbAC( ) {
return AC. s i z e ( ) ;
}
/

getNbCoef
ret ourne l e nombre de coef

/
i nt DCTCoef : : getNbCoef ( ) {
return getNbAC()+getNbDC( ) ;
}
/

getNbACEqualsTo
ret ourne l e nombre de c o e f f i c i e n t s AC gaux l a v al e ur abs ol ue de v al
\param v al val eur t e s t e r

/
i nt DCTCoef : : getNbACEqualsTo ( i nt val ) {
i nt compteur = 0;
for ( i nt i = 0 ; i < AC. s i z e ( ) ; i ++)
{
i f ( abs (AC[ i ] ) == val )
{
compteur++;
}
}
return compteur ;
}
/
38

getIthAC
ret ourne l e ieme coef AC
\param i i ndi c e du coef r et our ner

/
i nt DCTCoef : : getIthAC( i nt i ) {
return AC[ i ] ;
}
/

set It hAC
modi f i e l e ieme coef AC
\param i l i ndi c e du coef a modi f i er
\param v al l a val e ur met t re l a pl ace

/
void DCTCoef : : setIthAC( i nt i , i nt val ) {
AC[ i ] = val ;
}
/

setIthACLSB
modi f i e l e l s b de ieme coef AC
\param i l i ndi c e du coef a modi f i er
\param v al l a val e ur du l s b met t re l a pl ace

/
void DCTCoef : : setIthACLSB( i nt i , i nt val ) {
i f ( ( val != 0) && ( val != 1) )
{
throw runti me_error ( "DCTCoef : : setIthACLSB : l a val eur dunouveauLSB doi t tre s o i t 0 s o i t 1 ! " ) ;
}
i f ( val != l s b ( getIthAC( i ) ) )
{
i nt newVal = ( getIthAC( i ) >= 0) ? getIthAC( i )+1 : getIthAC( i )1 ;
setIthAC( i , newVal ) ;
}
i f ( val != l s b ( getIthAC( i ) ) )
{
throw( st d : : runti me_error ( "DCTCoef : : setIthACLSB : modi f i c at i on duLSB i nc o r r e c t e " ) ) ;
e xi t ( 1);
}
}
/

39
getIthDC
ret ourne l e ieme coef DC
\param i l i ndex du coef DC que l on recherche

/
i nt DCTCoef : : getIthDC( i nt i ) {
return DC[ i ] ;
}
/
l s b
ret ourne l e l s b d un e nt i e r
\param n l e nt i e r

/
i nt DCTCoef : : l s b ( i nt n) {
// p o s i t i f + i mpai r OU ne g a t i f + pai r => 1
// p o s i t i f + pai r OU ne g a t i f + i mpai r => 0
i f ( ( ( n > 0) && ( n%2 != 0) ) | | ( ( n < 0 ) && ( n%2 == 0) ) )
{
return 1;
}
el se
{
return 0;
}
}
40
A.3 compress.cpp
#include " . . / image/image . H"
#include " . . / image/ i magei o . H"
#include " . . / image/ i maget ool s . H"
#include " . . / image/ dct . h"
#include <c s t dl i b >
#include <s t di o . h>
#include <c s t r i ng >
#include <f stream>
#include <math . h>
#include <s t r i ng >
#include <i ostream>
using namespace std ;
char IMAGE_IN;
char IMAGE_OUT;
i nt QUALITY_FACTOR;
/
proccessOpt i onsI nLi ne
t r a i t e l e s opt i ons d e x c u t i o n
\param argc
\param argv

/
void pr oces s Opt i ons I nLi ne ( i nt argc , char argv )
{
i f ( ( argc != 4) )
{
cout << "\nUsage : " << argv [ 0 ] << "i mageIn . pgmimageOut . pgm Qual i t yFact or \n" ;
e xi t ( 1);
}
IMAGE_IN = new char [ 2 0 0 ] ;
IMAGE_OUT = new char [ 2 0 0 ] ;
// r ecopi e des p a r a m t r e s dans l e s v a r i a b l e s
s t r cpy (IMAGE_IN, argv [ 1 ] ) ;
s t r cpy (IMAGE_OUT, argv [ 2 ] ) ;
char qual i t yFact or = new char [ 3 ] ; s t r cpy ( qual i t yFact or , argv [ 3 ] ) ;
QUALITY_FACTOR = at oi ( qual i t yFact or ) ;
i f ( (QUALITY_FACTOR < 0 ) | | (QUALITY_FACTOR > 100) )
{
cout << "\ nError : l e f ac t e ur de q u a l i t doi t tre compri s ent r e 0 et 100 ! \ n" ;
e xi t ( 1);
}
}
41
/
compress
si mul e une compressi on j peg
\param imageIn image d e n t r e
\param QF f ac t e ur de q u a l i t . 0 < QF < 100

/
Image<oct et > compress ( Image<oct et > imageIn , i nt QF)
{
Image<oct et > imageOut = new Image<oct et >(i mageIn . NbRow( ) , i mageIn . NbCol ( ) ) ;
i nt hei ght = i mageIn . NbRow( ) ;
i nt wi dth = i mageIn . NbCol ( ) ;
// c ons t r uc t i on de l a t a b l e de q u a nt i f i c a t i o n
i nt tabRef [ 8 8 ] = { 16 , 11 , 10 , 16 , 24 , 40 , 51 ,
61 ,
12 , 12 , 14 , 19 , 26 , 58 ,
60 , 55 ,
14 , 13 , 16 , 24 , 40 , 57 , 69 , 56 ,
14 , 17 , 22 , 29 , 51 , 87 ,
80 , 62 ,
18 , 22 , 37 , 56 , 68 , 109 , 103 , 77 ,
24 , 35 , 55 , 64 , 81 , 104 , 113 , 92 ,
49 , 64 , 78 , 87 , 103 , 121 , 120 , 101 ,
72 , 92 , 95 , 98 , 112 , 100 , 103 , 99 };
// p a r a m t r e c (Q)
double cQ;
i f (QF < 50)
{
cQ = 50000/(QF+1);
}
el se
{
cQ = 200 2QF;
}
double tabQuant = new double [ 8 8 ] ;
for ( i nt i = 0 ; i < 88 ; i ++)
{
tabQuant [ i ] = tabRef [ i ] cQ/100 ;
}
for ( i nt row = 0 ; row < hei ght /8 ; row++)
{
for ( i nt c ol = 0 ; c ol < wi dth/8 ; c ol ++)
{
// premi er lement du b l oc
42
i nt i 0 = row8 wi dth+c ol 8;
// r empl i s s age des coef
double bl oc = new double [ 8 8 ] ;
for ( i nt x = 0; x < 8 ; x++)
{
for ( i nt y = 0 ; y < 8 ; y++)
{
bl oc [ 8 y+x ] = i mageIn [ i 0+ywi dth+x ] ;
}
}
// dct convers i on
dct : : Data2DCT88( bl oc ) ;
// Di vi s i on
for ( i nt i = 0 ; i < 88 ; i ++)
{
bl oc [ i ] = round ( bl oc [ i ] / tabQuant [ i ] ) ;
bl oc [ i ] = tabQuant [ i ] ;
}
// i nv e r s e dct
dct : : DCT882Data( bl oc ) ;
// i ns e r t i o n des v al e ur s dans l image de s o r t i e
for ( i nt x = 0; x < 8 ; x++)
{
for ( i nt y = 0 ; y < 8 ; y++)
{
// recadrage des v al e ur s ent r e 0 et 255
( imageOut ) [ i 0+ywi dth+x ] = ( bl oc [ 8 y+x ] < 0 ? 0 : ( bl oc [ 8 y+x ] > 255 ? 255 : bl oc [ 8 y+x ] ) ) ;
}
}
}
}
return imageOut ;
}
/
main
Programme p r i nc i p a l . . .

/
i nt main( i nt argc , char argv )
{
/TRAITE LES OPTIONS/
pr oces s Opt i ons I nLi ne ( argc , argv ) ;
//LECTURE DE LIMAGE DENTREE
43
Image<oct et > i mageIn ;
ImageIO<oct et >: :ReadPGM(IMAGE_IN, i mageIn ) ;
Image<oct et > imageOut = new Image<oct et >(i mageIn . NbRow( ) , i mageIn . NbCol ( ) ) ;
//COMPRESSION
imageOut = compress ( imageIn , QUALITY_FACTOR) ;
//SAUVEGARDE DE LIMAGE
ImageIO<oct et >: : WritePGM(IMAGE_OUT, imageOut ) ;
cout << "\ nFi chi e r c o mp r e s s dans : " ; for ( i nt i = 0 ; i < 200 ; i ++) cout << IMAGE_OUT[ i ] ; cout << endl ;
return 0;
}
44
A.4 Embedding.h
/
Name : Embedding
aut hor : R mi Watri gant
dat e : 30/04/09
Des cr i pt i on : i n s r e un message dans une image en u t i l i s a n t l al gor i t hme F5
de West f el d
/
#i f ndef EMBEDDING_H
#define EMBEDDING_H
#include " . . / image/image . H"
#include " . . / image/ i magei o . H"
#include " . . / image/ i maget ool s . H"
#include " . . / image/ dct . h"
#include " . . / image/DCTCoef . h"
#include <f stream>
#include <math . h>
#include <i ostream>
using namespace std ;
typedef vector <int> Message ;
cl ass Embedding {
private :
/
p a r a m t r e s d e n t r e / s o r t i e s de l al go
/
Image<oct et > i mageIn ;
Image<oct et > imageOut ;
i nt qual i t yFact or ;
i nt stegoKey ;
/
s t a t s
/
i nt s i zeMes s age ;
i nt s i zeI mage ;
double r e l at i ve _l e ngt h ;
i nt nb_usabl e_coef ;
i nt nb_of_bits_embedded ;
i nt NOM_ME; // Number Of Modi f i cat i ons due t o Matri x Embedding
i nt NOM_SK; // Number Of Modi f i cat i ons due t o SKrinkage
i nt NOM_all ; // NOM_ME + NOM_SK
double embeddi ng_ef f i ci ency ;
double r el at i ve_nb_of _modi f i cat i ons ; // Re l at i v e Number of Modi f i cat i ons = NOM_ALL / number of AC coef
45
/
l e message et l e coverWork dans l al go
/
Message message ;
DCTCoef coverWork ;
/
t a b l e de q ua nt i f i c a t i o n pour l a compressi on
/
double tabQuant ;
/
l e s p a r a m t r e s t e chni ques de l al go
/
i nt parameter_S ;
i nt parameter_N ;
i nt nbChangements ;
i nt H;
/
s t ockage des b i j e c t i o n s pour m l a n g e r l e message et l e coverWork
/
i nt coverWorkBi j ecti on ;
i nt cover Wor kBi j ect i onI nver s e ;
i nt mes s ageBi j ect i on ;
i nt me s s age Bi j e c t i onI nve r s e ;
/
i ni t H
i n i t i a l i s e l a mat ri ce H u t i l i s e dans l al go
p a r t i r du p a r a m t r e n et s

/
void i ni t H ( ) ;
/
convert Int ToBi n
c o nv e r t i t un nombre en un nombre en base 2
\param number l e nombre c onv e r t i r
\param bi nary p a r a m t r e d e n t r e / s o r t i e
\param s i z e l e nombre de b i t s sur l e s q u e l coder l e nombre

/
void convertIntToBi n ( i nt number , i nt bi nary , i nt s i z e ) ;
/
convertCharToBin
c o nv e r t i t un c a r a c t r e en un nombre en base 2
\param mess l e c a r a c t r e c onv e r t i r
\param bi nary p a r a m t r e d e n t r e / s o r t i e

/
46
void convertCharToBi n ( char mess , i nt bi nary ) ;
/
b ui l d Bi j e c t i o n
c r une b i j e c t i o n de [ 1 , n] dans l u i m me
\param n borne max de l ensembl e

/
i nt bui l dBi j e c t i o n ( i nt n ) ;
/
getRandomInt
ret ourne un e nt i e r a l a t o i r e ent r e [ 0 , bSup ]
\param bSup l a borne sup de l i n t e r v a l l e

/
i nt getRandomInt ( i nt bSup ) ;
/
l s b
ret ourne l e l s b d un e nt i e r
\param n l e nt i e r

/
i nt l s b ( i nt n ) ;
public :
/
Const ruct eur
i n i t i a l i s a t i o n des p a r a m t r e s du programme
\param support Pat h chemin de l image du support
\param st egoPat h chemin de l image de s o r t i e du programme
\param messagePath chemin du f i c h i e r cont enant l e message i n s r e r
\param st egoKey mot de passe ne c e s s ai r e pour d f i n i r l e s marches a l a t o i r e s
\param q ual i t yFac t or f ac t e ur de q u a l i t de compressi on j peg

/
Embedding ( char supportPath ,
char stegoPath ,
char messagePath ,
i nt stegoKey ,
i nt qual i t yFac t or ) ;
/
de s t r uc t e ur
/
~Embedding ( ) ;
/
pr i nt Re s ul t s
Af f i c he des i nf ormat i on sur l i ns e r t i o n
/
void pr i nt Re s ul t s ( ) ;
47
/
setIsMessageTooLong
i ndi que que l a t a i l l e du message e s t t rop l ongue
/
void setIsMessageTooLong ( bool isTooLong ) ;
/
compress
si mul e une compressi on j peg j us qu l a q u a nt i f i c a t i o n sur l image d e n t r e

/
void compressi on ( ) ;
/
computeCapaci ty
c a l c ul e l a c a p a c i t d i ns e r t i o n sur l image d e n t r e ,
l e p a r a m t r e d i ns e r t i on , l a t a i l l e du message dans l e support

/
void computeCapaci ty ( ) ;
/
shuf f l eCoverWork
m l a n g e a l a t o i r e me n t l e support l ai de du mot de passe

/
void shuf f l eCoverWork ( ) ;
/
s huf f l eMes s age
m l a n g e l e message l ai de du mot de passe

/
void s huf f l eMes s age ( ) ;
/
hi de Si z e s
cache l e p a r a m t r e de l al go et l a t a i l l e du message dans l image
dans l e s premi ers b i t s du support , en u t i l i s a n t l a t echni que LSB

/
void hi de Si z e s ( ) ;
/
matrixEmbedding
i n s r e l e message en u t i l i s a n t l a t echni que de matrixEmbedding

/
void matrixEmbedding ( ) ;
48
/
unShuf f l eCoverWork
r a r r a n g e l e coverWork dans l ordre

/
void unShuffl eCoverWork ( ) ;
/
saveSt egoImage
sauvegarde l image . j pegLi ke et l image decompressee . pgm
\param st egoPat h l e chemin de l image de s o r t i e

/
void saveImage ( char stegoPath ) ;
/
saveHi st ogram
e nr e g i s t r e l histogramme des coef AC
\para hi s t oPat h l e chemin du f i c h i e r e t r e e n r e g i s t r
/
void saveHi stogram ( char hi st oPat h ) ;
/
f onc t i on de t e s t des m t h o d e s

/
void t e s t ( ) ;
};
#endif
49
A.5 Embedding.cpp
/
Name : Embedding
aut hor : R mi Watri gant
dat e : 30/04/09
Des cr i pt i on : i n s r e un message dans une image en u t i l i s a n t l al gor i t hme F5
de West f el d
/
#include "Embedding . h"
#include <math . h>
#include <stdexcept >
/
Const ruct eur
i n i t i a l i s a t i o n des p a r a m t r e s du programme
\param support Pat h chemin de l image du support
\param st egoPat h chemin de l image de s o r t i e du programme
\param messagePath chemin du f i c h i e r cont enant l e message i n s r e r
\param st egoKey mot de passe ne c e s s ai r e pour d f i n i r l e s marches a l a t o i r e s
\param q ual i t yFac t or f ac t e ur de q u a l i t de compressi on j peg

/
Embedding : : Embedding ( char supportPath ,
char stegoPath ,
char messagePath ,
i nt stegoKey ,
i nt qual i t yFac t or ) {
this>stegoKey = stegoKey ;
this>qual i t yFac t or = qual i t yFact or ;
//LECTURE DE LIMAGE DENTREE
ImageIO<oct et >: :ReadPGM( supportPath , i mageIn ) ;
//LECTURE DU MESSAGE
FILE f i c h i e r = f open ( messagePath , " r " ) ;
char currCar ;
vector <char> messageSt ri ng ;
i f ( f i c h i e r != NULL)
{
do
{
currCar = f g e t c ( f i c h i e r ) ; // On l i t l e c a r a c t r e
messageStri ng . push_back ( currCar ) ;
} while ( currCar != EOF) ; // On cont i nue t ant que f g e t c n a pas r e t o u r n EOF ( f i n de f i c h i e r )
f c l o s e ( f i c h i e r ) ;
}
el se
{
50
cout << " Pr o bl me d ouver t ur e dumessage \n" ;
e xi t ( 1);
}
//TRANSFORMATION DU MESSAGE EN BINAIRE
i nt bi nary = new i nt [ 8 ] ;
i nt b ;
for ( i nt i =0, b=0 ; i < messageSt ri ng . s i z e ( ) ; i ++, b+=8)
{
convertCharToBi n ( messageStri ng [ i ] , bi nary ) ; //on c o nv e r t i t l e message en b i nai r e
for ( i nt j = 0 ; j < 8 ; j ++) message . push_back ( bi nary [ j ] ) ; //on l e met dans l a t t r i b u t message
}
}
/
de s t r uc t e ur
/
Embedding : : ~ Embedding ( ) {
delete tabQuant ;
delete coverWorkBi j ecti on ;
delete cover Wor kBi j ect i onI nver s e ;
delete mes s ageBi j ect i on ;
delete me s s age Bi j e c t i onI nve r s e ;
for ( i nt i = 0 ; i < parameter_N ; i ++)
{
delete H[ i ] ;
}
delete H;
}
/
compress
si mul e une compressi on j peg j us qu l a q ua nt i f i c a t i o n sur l image d e n t r e
sauvegarde l e s c o e f f i c i e n t s DCT dans une s t r uc t ur e DCTCoef

/
void Embedding : : compressi on ( ) {
i nt tabRef [ 8 8 ] = { 16 , 11 , 10 , 16 , 24 , 40 , 51 ,
61 ,
12 , 12 , 14 , 19 , 26 , 58 , 60 ,
55 ,
14 , 13 , 16 , 24 , 40 , 57 , 69 , 56 ,
14 , 17 , 22 , 29 , 51 , 87 , 80 ,
62 ,
18 , 22 , 37 , 56 , 68 , 109 , 103 , 77 ,
24 , 35 , 55 , 64 , 81 , 104 , 113 , 92 ,
49 , 64 , 78 , 87 , 103 , 121 , 120 , 101 ,
72 , 92 , 95 , 98 , 112 , 100 , 103 , 99 };
vector <int> DC;
51
vector <int> AC;
i nt hei ght = i mageIn . NbRow( ) ;
i nt wi dth = i mageIn . NbCol ( ) ;
// c ons t r uc t i on de l a t a b l e de q u a nt i f i c a t i o n
// p a r a m t r e c (Q)
double cQ;
i f ( qual i t yFact or < 50)
{
cQ = 50000/( qual i t yFac t or +1);
}
el se
{
cQ = 200 2 qual i t yFact or ;
}
tabQuant = new double [ 8 8 ] ;
for ( i nt i = 0 ; i < 88 ; i ++)
{
tabQuant [ i ] = tabRef [ i ] cQ/100 ;
}
for ( i nt row = 0 ; row < hei ght /8 ; row++)
{
for ( i nt c ol = 0 ; c ol < wi dth/8 ; c ol ++)
{
// premi er lement du b l oc
i nt i 0 = row8 wi dth+c ol 8;
// r empl i s s age des coef
double bl oc = new double [ 8 8 ] ;
for ( i nt x = 0; x < 8 ; x++)
{
for ( i nt y = 0 ; y < 8 ; y++)
{
bl oc [ 8 y+x ] = i mageIn [ i 0+ywi dth+x ] ;
}
}
// dct convers i on
dct : : Data2DCT88( bl oc ) ;
// Di vi s i on
for ( i nt i = 0 ; i < 88 ; i ++)
{
bl oc [ i ] = round ( bl oc [ i ] / tabQuant [ i ] ) ;
}
52
// i ns e r t i o n des v al e ur s dans l e s v e c t e ur s t emporai res DC et AC
DC. push_back ( bl oc [ 0 ] ) ;
for ( i nt i = 1 ; i < 64 ; i ++)
{
AC. push_back ( bl oc [ i ] ) ;
}
}
}
// i n i t i a l i s a t i o n de l a t t r i b u t coverWork avec l e s deux v e c t e ur s c r s
coverWork . setAC(AC) ;
coverWork . setDC(DC) ;
}
/
computeCapaci ty
c a l c ul e l a c a p a c i t d i ns e r t i o n sur l image d e n t r e ,
l e p a r a m t r e d i ns e r t i on , l a t a i l l e du message dans l e support

/
void Embedding : : computeCapaci ty ( ) {
// c a p a c i t e s t i m e sans matrixEmbedding
i nt capaci t y = round ( coverWork . getNbCoef ( ) coverWork . getNbDC( ) coverWork . getNbACEqualsTo ( 0) coverWork . getNbACEqualsTo ( 1) + 0. 49 coverWork . getNbACEqualsTo ( 1 ) ) ;
// s i l a t a i l l e r e l a t i v e e s t s u p r i e u r e 2/3 c e l a ne s e r t r i en d i n s r e r
i f ( message . s i z e ( ) >= ( 2. /3) capaci t y )
{
cout << endl << endl << " Attenti on : tout l e message n apas pu tre i n s r " << endl << endl ;
message . r e s i z e ( round ( ( 2. /3) capaci t y ) ( ( i nt ) round ( ( 2. /3) capaci t y ) % 8) ) ;
}
// i l f aut chercher l e nombre de changements e f f e c t u e r
// i . e l e nombre de f o i s qu i l f aut d i v i s e r l e message et l e coverWork
bool trouve = f al se ;
nbChangements = 1;
// i n u t i l e de devoi r c a l c u l e r 2^n pour des v al e ur s t r ops grandes
while ( ( message . s i z e ( ) / nbChangements ) > 28 )
{
nbChangements++;
}
// nbChangements 2^( message . s i z e ( ) / nbChangements ) e s t l a t a i l l e du coverWork ne c e s s ai r e pour n e f f e c t u e r que nbChangements changements sur c e l u i c i
// s i c e s t s u p r i e u r au coverWork i l f aut al or s encore d i v i s e r
while ( ! trouve )
{
trouve = nbChangements ( pow( 2 , c e i l ( ( f l oat ) message . s i z e ( ) / nbChangements ) ) 1 ) <= capaci t y ;
53
//on prend l arrondi s u p r i e u r de l a d i v i s i o n f l o t t a n t e parce que
//par exempl e s i l on veut d c o u p e r un message de 17 en 2 i l f aut des "morceaux" de 9 b i t s
// autrement s i l on prend 8 l e message ne sera pas t ransmi s compl etement (28=16)
//on i n s r e al or s 29=18 b i t s ( bourrage )
nbChangements++;
}
nbChangements; // ( on a i n c r m n t pour r i en avant de s o r t i r )
// recherche de l a nouv e l l e t a i l l e du message s i l y a bourrage
i nt newSi ze = message . s i z e ( ) ;
while ( ( newSi ze % nbChangements ) != 0 )
{
newSi ze++;
}
i nt bourrage = newSi ze message . s i z e ( ) ;
/ DEBUG / /
i f ( newSi ze != message . s i z e ( ) )
{
cout << "Bourrage : " << bourrage << endl ;
}
/ DEBUG /
s i zeMes s age = message . s i z e ( ) ;
// i l f aut de c al e r message de ( newSi ze message . s i z e ( ) ) b i t s ver s l a dr oi t e pour r empl i r l e message t r ans met t r e
for ( i nt i = 0 ; i < bourrage ; i ++)
{
//on i n s r e un z r o au debut
message . i ns e r t ( message . begi n ( ) , 0 ) ;
}
// c a l c u l des p a r a m t r e s S et N de l al go
parameter_S = message . s i z e ( ) / nbChangements ;
parameter_N = ( i nt ) pow( 2 , parameter_S ) 1;
/DEBUG/ /
cout << endl << endl << "\ t i nf o s sur l e s c apac i t e s : " << endl << endl ;
cout << "\ t \t nbCoef : " << coverWork . getNbCoef ( ) << endl ;
cout << "\ t \tnbDC : " << coverWork . getNbDC( ) << endl ;
cout << "\ t \ t c o e f a 0 : " << coverWork . getNbACEqualsTo (0) << endl ;
cout << "\ t \ t c o e f a 1 : " << coverWork . getNbACEqualsTo (1) << endl ;
cout << "\ t \ t c apac i t y : " << capaci t y << endl ;
cout << "\ t \ t paramet re de l al go : " << parameter_S << endl << endl ;
/DEBUG/
nb_usabl e_coef = coverWork . getNbAC( ) coverWork . getNbACEqualsTo ( 0 ) ;
NOM_ME = nbChangements ;
NOM_SK = 0; // ( i n i t i a l i s a t i o n )
embeddi ng_ef f i ci ency = parameter_S / (1pow( 2 , parameter_S ) ) ;
54
s i zeI mage = coverWork . getNbCoef ( ) ;
nb_of_bits_embedded = message . s i z e ( ) ; // a p r s bourrage
r e l at i ve _l e ngt h = ( f l oat ) s i zeMes s age / s i zeI mage ;
}
/
shuf f l eCoverWork
m l a n g e a l a t o i r e me n t l e support l ai de du mot de passe

/
void Embedding : : shuf f l eCoverWork ( ) {
srand ( stegoKey ) ;
coverWorkBi j ecti on = new i nt [ coverWork . getNbAC ( ) ] ;
cover Wor kBi j ect i onI nver s e = new i nt [ coverWork . getNbAC ( ) ] ;
coverWorkBi j ecti on = bui l dBi j e c t i o n ( coverWork . getNbAC ( ) ) ;
vector <int> randomACCoef ;
randomACCoef . r e s i z e ( coverWork . getNbAC ( ) ) ;
for ( i nt i = 0 ; i < coverWork . getNbAC( ) ; i ++)
{
cover Wor kBi j ect i onI nver s e [ coverWorkBi j ecti on [ i ] ] = i ;
randomACCoef [ i ] = coverWork . getIthAC( coverWorkBi j ecti on [ i ] ) ;
}
coverWork . setAC( randomACCoef ) ;
}
/
s huf f l eMes s age
m l a n g e l e message l ai de du mot de passe

/
void Embedding : : s huf f l eMes s age ( ) {
/DEBUG/ /
cout << "Message non m l a n g : " << endl ;
f or ( i nt i = 0 ; i < message . s i z e ( ) ; i ++)
{
cout << message [ i ] << " ";
}
cout << endl ;
/DEBUG/
srand ( stegoKey ) ;
mes s ageBi j ect i on = new i nt [ message . s i z e ( ) ] ;
me s s age Bi j e c t i onI nve r s e = new i nt [ message . s i z e ( ) ] ;
55
mes s ageBi j ect i on = bui l dBi j e c t i o n ( message . s i z e ( ) ) ;
Message randomMessage ;
randomMessage . r e s i z e ( message . s i z e ( ) ) ;
for ( i nt i = 0 ; i < message . s i z e ( ) ; i ++)
{
me s s age Bi j e c t i onI nve r s e [ mes s ageBi j ect i on [ i ] ] = i ;
randomMessage [ i ] = message [ mes s ageBi j ect i on [ i ] ] ;
}
message . swap( randomMessage ) ;
}
/
hi de Si z e s
cache l e p a r a m t r e de l al go et l a t a i l l e du message dans l image
dans l e s premi ers b i t s du support , en u t i l i s a n t l a t echni que LSB
( codage de chaque e nt i e r sur 32 b i t s )

/
void Embedding : : hi de Si z e s ( ) {
i nt NBBITS = 32;
i nt s_bi nary = new i nt [ NBBITS ] ;
i nt s i ze_bi nar y = new i nt [ NBBITS ] ;
for ( i nt i = 0 ; i < NBBITS ; i ++)
{
s_bi nary [ i ] = 0;
s i ze_bi nar y [ i ] = 0;
}
convertIntToBi n ( parameter_S , s_binary , 32) ;
convertIntToBi n ( message . s i z e ( ) , si ze_bi nary , 32) ;
for ( i nt i = 0 ; i < NBBITS ; i ++)
{
coverWork . setIthACLSB( i , s_bi nary [ i ] ) ;
coverWork . setIthACLSB( i +32, s i ze_bi nar y [ i ] ) ;
}
/DEBUG/ /
cout << "Parametres i ns e r e s : " << endl ;
cout << "\ t Parametre s : " << parameter_S << endl ;
cout << "\ t Ta i l l e : " << message . s i z e ( ) << endl << endl ;
cout << "\ t Parametre n : " << parameter_N << endl ;
/DEBUG/
}
/
56
matrixEmbedding
i n s r e l e message en u t i l i s a n t l a t echni que de matrixEmbedding

/
void Embedding : : matrixEmbedding ( ) {
// i n i t i a l i s a t i o n de l a mat ri ce H
i ni t H ( ) ;
i nt compteur = 64; // i n c r m e n t sur l e s AC du coverWork
//commencement 64 car on i n s r l e p a r a m t r e et l a t a i l l e du message avant
;
for ( i nt changement = 0 ; changement < nbChangements ; changement++)
{
// b uf f e r de s lments du message
i nt buf f Mess = new i nt [ parameter_S ] ;
for ( i nt i = 0 ; i < parameter_S ; i ++)
{
buf f Mess [ i ] = message [ changement parameter_S + i ] ;
}
// b uf f e r de n lments du coverWork
//on m mor i s e l e s i ndex des lments
i nt buffCoverWorkId = new i nt [ parameter_N ] ;
for ( i nt i = 0 ; i < parameter_N ; i ++)
{
buffCoverWorkId [ i ] = compteur ;
compteur = coverWork . getIthNextNonZeroAC( compteur ) ;
}
i nt Hx = new i nt [ parameter_S ] ;
i nt He = new i nt [ parameter_S ] ;
i nt e_B10 ;
EFFONDREMENT:
// c a l c u l de Hx
for ( i nt i = 0 ; i < parameter_S ; i ++)
Hx[ i ] = 0;
for ( i nt i = 0 ; i < parameter_S ; i ++)
{
for ( i nt j = 0 ; j < parameter_N ; j ++)
Hx[ i ] += ( l s b ( coverWork . getIthAC( buffCoverWorkId [ j ] ) ) H[ j ] [ i ] ) % 2 ;
Hx[ i ] %= 2 ;
}
// c a l c u l de mHx = He
57
for ( i nt i = 0 ; i < parameter_S ; i ++)
He [ i ] = ( buf f Mess [ i ] + Hx[ i ] ) % 2 ;
// c a l c u l de e
//e_B10 e s t l a r e p r s e n t a t i o n en base 10 de e
e_B10 = 0;
for ( i nt i = 0 ; i < parameter_S ; i ++)
{
e_B10 += He [ i ] ( i nt )pow( 2 , parameter_Si 1);
}
e_B10;
i f ( e_B10 >=0 )
{
i nt newAC = ( coverWork . getIthAC( buffCoverWorkId [ e_B10 ] ) > 0 ?
coverWork . getIthAC( buffCoverWorkId [ e_B10]) 1 : coverWork . getIthAC( buffCoverWorkId [ e_B10] )+1) ;
coverWork . setIthAC( buffCoverWorkId [ e_B10 ] , newAC )
;
// ef f ondrement ?
i f ( coverWork . getIthAC( buffCoverWorkId [ e_B10 ] ) == 0)
{
NOM_SK++;
for ( i nt i = e_B10 ; i < parameter_N1 ; i ++)
{
buffCoverWorkId [ i ] = buffCoverWorkId [ i +1] ;
}
buffCoverWorkId [ parameter_N1] = compteur ;
compteur = coverWork . getIthNextNonZeroAC( compteur ) ;
goto EFFONDREMENT;
}
}
}
NOM_all = NOM_ME + NOM_SK;
r el at i ve_nb_of _modi f i cat i ons = ( f l oat )NOM_all / nb_usabl e_coef ;
}
/
unShuf f l eCoverWork
r a r r a n g e l e coverWork dans l ordre

/
void Embedding : : unShuffl eCoverWork ( ) {
vector <int> newCoverWork ;
newCoverWork . r e s i z e ( coverWork . getNbAC ( ) ) ;
58
for ( i nt i = 0 ; i < coverWork . getNbAC( ) ; i ++)
{
newCoverWork [ i ] = coverWork . getIthAC( cover Wor kBi j ect i onI nver s e [ i ] ) ;
}
coverWork . setAC( newCoverWork ) ;
}
/
saveSt egoImage
sauvegarde l image . j pegLi ke et l image decompressee . pgm
\param st egoPat h l e chemin de l image de s o r t i e

/
void Embedding : : saveImage ( char stegoPath ) {
i nt hei ght = i mageIn . NbRow( ) ;
i nt wi dth = i mageIn . NbCol ( ) ;
//ECRITURE DU FICHIER . j pegLi ke
s t r i ng st rSt egoPat h ( stegoPath ) ;
st rSt egoPat h . e r as e ( st rSt egoPat h . end() 4 , st rSt egoPat h . end ( ) ) ;
st rSt egoPat h += " . j pegLi ke " ;
of st ream f i c h i e r ( st rSt egoPat h . c_str ( ) , i o s : : out | i o s : : trunc ) ;
// ouver t ur e en criture avec ef f acement du f i c h i e r ouver t
i f ( f i c h i e r )
{
i nt cptDC = 0;
i nt cptAC = 0;
i nt i = 0;
while ( i < coverWork . getNbAC( ) + coverWork . getNbDC( ) )
{
f i c h i e r << coverWork . getIthDC( cptDC) << endl ;
cptDC++; i ++;
for ( i nt k = 0 ; k < 63 ; k++)
{
f i c h i e r << coverWork . getIthAC( cptAC) << endl ;
cptAC++;
i ++;
}
}
f i c h i e r . c l o s e ( ) ;
}
el se
c e r r << " I mpos s i bl e d ouvr i r l e f i c h i e r ! " << endl ;
//ECRITURE DU FICHIER .PGM
59
Image<oct et > temp( hei ght , wi dth ) ;
i nt cptDC = 0;
i nt cptAC = 0;
for ( i nt row = 0 ; row < hei ght /8 ; row++)
{
for ( i nt c ol = 0 ; c ol < wi dth/8 ; c ol ++)
{
// premi er lement du b l oc
i nt i 0 = row8 wi dth+c ol 8;
double bl oc = new double [ 8 8 ] ;
//on remet not re DC
bl oc [ 0 ] = coverWork . getIthDC( cptDC) tabQuant [ 0 ] ;
cptDC++;
// pui s on met l e s AC
for ( i nt j = 1 ; j < 88 ; j ++)
{
bl oc [ j ] = coverWork . getIthAC( cptAC) tabQuant [ j ] ;
cptAC++;
}
dct : : DCT882Data( bl oc ) ;
for ( i nt x = 0; x < 8 ; x++)
{
for ( i nt y = 0 ; y < 8 ; y++)
{
i nt c oe f = ( i nt ) bl oc [ 8 y+x ] ;
temp [ i 0+ywi dth+x ] = ( c oe f > 255) ? 255 : ( ( c oe f < 0) ? 0 : c oe f ) ;
}
}
}
}
imageOut = temp ;
ImageIO<oct et >: : WritePGM( stegoPath , imageOut ) ;
}
/
saveHi st ogram
e nr e g i s t r e l histogramme des coef AC
\para hi s t oPat h l e chemin du f i c h i e r e t r e e n r e g i s t r
60
/
void Embedding : : saveHi stogram ( char hi stoPat h ) {
i nt borne = 6;
vector <int> hi stogram ;
for ( i nt i = 0 ; i < 2 borne ; i ++)
{
hi stogram . push_back ( 0 ) ;
}
i nt mi l i eu = borne ;
for ( i nt i = 0 ; i < coverWork . getNbAC( ) ; i ++)
{
i f ( ( coverWork . getIthAC( i ) > borne ) && ( coverWork . getIthAC( i ) < borne ) && ( i % 65 == 1) )
{
hi stogram [ borne + coverWork . getIthAC( i )] ++;
}
}
of st ream f i l e ( hi stoPath , i o s : : out | i o s : : trunc ) ; // ouver t ur e en criture avec ef f acement du f i c h i e r ouvert
i f ( f i l e )
{
for ( i nt i = ( 1) borne ; i < borne ; i ++)
{
f i l e << i << "" << hi stogram [ borne + i ] << endl ;
}
f i l e . c l o s e ( ) ;
}
el se
c e r r << " I mpos s i bl e d ouvr i r l e f i c h i e r ! " << endl ;
}
/
pr i nt Re s ul t s
Af f i c he des i nf ormat i on sur l i ns e r t i o n
/
void Embedding : : pr i nt Re s ul t s ( ) {
cout << endl << "\ t R s u l t a t s : " << endl << endl ;
cout << "\ t \ t Ta i l l e dumessage : " << s i zeMes s age << " bi t s " << endl ;
cout << "\ t \ t Ta i l l e de l image : " << s i zeI mage << " bi t s " << endl ;
cout << "\ t \ t Ta i l l e r e l a t i v e : " << r e l at i ve _l e ngt h << endl ;
cout << "\ t \ t " << nb_of_bits_embedded << " bi t s i n s r s " << endl ;
cout << "\ t \tEmbedding e f f i c i e n c y : " << embeddi ng_ef f i ci ency << endl ;
cout << "\ t \ t " << NOM_ME << " modi f i c at i ons dues aumatri xembedding" << endl ;
cout << "\ t \ t " << NOM_SK << " modi f i c at i ons dues aux ef f ondr ement s " << endl ;
61
cout << "\ t \ t " << NOM_all << " modi f i c at i ons au t o t a l " << endl ;
cout << "\ t \ t " << "Nombrede modi f i c at i ons r e l a t i v e s : " << r el at i ve_nb_of _modi f i cat i ons << endl << endl ;
}
/
i ni t H
i n i t i a l i s e l a mat ri ce H u t i l i s e dans l al go
p a r t i r du p a r a m t r e n et s

/
void Embedding : : i ni t H ( ) {
H = new i nt [ parameter_N ] ; // mat ri ce H de 2^s 1 l i g ne s et s col onnes
for ( i nt i = 0 ; i < parameter_N ; i ++) // c ont i e nt t ous l e s e nt i e r s de 1 2^s 1 en b i nai r e sur l e s l i g ne s
{
H[ i ] = new i nt [ parameter_S ] ;
}
// c a l c u l de l a mat ri ce H
for ( i nt i = 0 ; i < parameter_N ; i ++)
{
convertIntToBi n ( i +1, H[ i ] , parameter_S ) ;
}
}
/
convert Int ToBi n
c o nv e r t i t un nombre en un nombre en base 2
\param number l e nombre c onv e r t i r
\param bi nary p a r a m t r e d e n t r e / s o r t i e
\param s i z e l e nombre de b i t s sur l e s q u e l coder l e nombre

/
void Embedding : : convertIntToBi n ( i nt number , i nt bi nary , i nt s i z e ) {
//On s t oc k e dans l e vect eur des poi ds f a i b l e s ver s l e s poi ds f o r t s .
for ( i nt i =0; i <s i z e ; i ++)
{
bi nary [ i ] = ( ( number>>i )&1);
i f ( ( bi nary [ i ] != 0) && ( bi nary [ i ] != 1) ) {
cout<<" convertIntToBi n : Converti onen bi na i r e n e s t pas bonne\n" ;
e xi t ( 1 ) ;
}
}
//on i nv e r s e l e t ab l e au
for ( i nt j = 0 ; j < s i z e /2 ; j ++)
{
i nt tmp = bi nary [ j ] ;
62
bi nary [ j ] = bi nary [ s i z e j 1] ;
bi nary [ s i z e j 1] = tmp;
}
}
/
convertCharToBin
c o nv e r t i t un c a r a c t r e en un nombre en base 2
\param mess l e c a r a c t r e c onv e r t i r
\param bi nary p a r a m t r e d e n t r e / s o r t i e

/
void Embedding : : convertCharToBi n ( char mess , i nt bi nary ) {
//On s t oc k e dans l e vect eur des poi ds f a i b l e s ver s l e s poi ds f o r t s .
for ( i nt i =0; i <8; i ++)
{
bi nary [ i ] = ( ( mess>>i )&1);
i f ( ( bi nary [ i ] != 0) && ( bi nary [ i ] != 1) ) {
cout<<" convertIntToBi n : Converti onen bi na i r e n e s t pas bonne\n" ;
e xi t ( 1 ) ;
}
}
//on i nv e r s e l e t ab l e au
for ( i nt j = 0 ; j < 4 ; j ++)
{
i nt tmp = bi nary [ j ] ;
bi nary [ j ] = bi nary [7j ] ;
bi nary [7j ] = tmp;
}
}
/
b ui l d Bi j e c t i o n
c r une b i j e c t i o n de [ 1 , n] dans l u i m me
\param n borne max de l ensembl e

/
i nt Embedding : : bui l dBi j e c t i o n ( i nt n) {
i nt i , j , nbelem ;
i nt f = new i nt [ n ] ;
vector <unsigned long int> l s t _i nt e ge r ( n ) ;
for ( i = 0 ; i < n ; i ++)
{
l s t _i nt e ge r [ i ] = i ;
}
i = 0;
for ( nbelem = n ; nbelem > 0 ; nbelem)
63
{
j = getRandomInt ( nbelem1);
f [ i ] = l s t _i nt e ge r [ j ] ;
l s t _i nt e ge r [ j ] = l s t _i nt e ge r [ nbelem1] ;
l s t _i nt e ge r . pop_back ( ) ;
i ++;
}
return f ;
}
/
getRandomInt
ret ourne un e nt i e r a l a t o i r e ent r e [ 0 , bSup ]
\param bSup l a borne sup de l i n t e r v a l l e

/
i nt Embedding : : getRandomInt ( i nt bSup) {
i f ( bSup <= 0)
return 0;
el se
return ( i nt ) ( i nt ) r i nt ( bSup( rand ( ) /( double)RAND_MAX) ) ;
}
/
f onc t i on de t e s t des m t h o d e s

/
void Embedding : : t e s t ( ) {
i nt n = 1024;
i nt bi nary = new i nt [ 3 2 ] ;
i nt i = 0;
i nt j = 321;
while ( i <= 32)
{
i f ( ( n >> i ) & 1)
{
bi nary [ j ] =1;
}
el se
{
bi nary [ j ] =0;
}
i ++;
j ;
64
}
// convert Int ToBi n (n , bi nary , 32) ;
cout << " r e p r s e n t a t i o n de" << n << "en bi na i r e : " ;
for ( i nt k = 0 ; k < 32 ; k++)
{
cout << bi nary [ k ] << "" ;
}
cout << endl ;
}
/
l s b
ret ourne l e l s b d un e nt i e r
\param n l e nt i e r

/
i nt Embedding : : l s b ( i nt n) {
// p o s i t i f + i mpai r OU ne g a t i f + pai r => 1
// p o s i t i f + pai r OU ne g a t i f + i mpai r => 0
i f ( ( ( n > 0) && ( n%2 != 0) ) | | ( ( n < 0 ) && ( n%2 == 0) ) )
{
return 1;
}
el se
{
return 0;
}
}
65
A.6 Extraction.h
/
Name : Ext r act i on
aut hor : R mi Watri gant
dat e : 30/04/09
Des cr i pt i on : e x t r a i t un message i n s r dans une image en u t i l i s a n t l al gor i t hme F5
de West f el d
/
#i f ndef EXTRACTION_H
#define EXTRACTION_H
#include " . . / image/image . H"
#include " . . / image/ i magei o . H"
#include " . . / image/ i maget ool s . H"
#include " . . / image/DCTCoef . h"
#include <i ostream>
#include <f stream>
#include <math . h>
#include <i ostream>
using namespace std ;
typedef vector <int> Message ;
cl ass Ext r act i on {
private :
/
p a r a m t r e s d e n t r e de l al go
/
char j pegl i ke Pat h ;
i nt qual i t yFac t or ;
i nt stegoKey ;
/
l e message et l e s coef de l image dans l al go
/
Message message ;
DCTCoef l s t Coe f ;
/
l e s p a r a m t r e s t e chni ques de l al go
/
i nt parameter_S ;
i nt s i zeMes s age ;
i nt parameter_N ;
i nt H;
/
s t ockage des b i j e c t i o n s pour m l a n g e r l e message et l e coverWork
/
i nt i mageBi j ect i on ;
66
i nt i mage Bi j e c t i onI nve r s e ;
i nt mes s ageBi j ect i on ;
i nt me s s age Bi j e c t i onI nve r s e ;
/
readFi l eAndFi l l LstDCT
l i t l e f i c h i e r et r e mpl i t l a l i s t e des coef DCT
\param f i c h i e r f l u x i st ream
/
void readFi l eAndFi l l LstDCT ( i f s t r e am f i c h i e r ) ;
/
f orEachBl ocExt ract i on
c a l c ul e l e syndrome d un bl oc , i e l e message qu i l c ont i e nt
\param supportRecu l e morceau de support
/
i nt f or EachBl ocExt r act i on ( i nt supportRecu ) ;
/
i ni t H
i n i t i a l i s e l a mat ri ce H u t i l i s e dans l al go
p a r t i r du p a r a m t r e n et s

/
void i ni t H ( ) ;
/
convert Int ToBi n
c o nv e r t i t un nombre en un nombre en base 2
\param number l e nombre c onv e r t i r
\param bi nary p a r a m t r e d e n t r e / s o r t i e
\param s i z e l e nombre de b i t s sur l e s q u e l coder l e nombre

/
void convertIntToBi n ( i nt number , i nt bi nary , i nt s i z e ) ;
/
b ui l d Bi j e c t i o n
c r une b i j e c t i o n de [ 1 , n] dans l u i m me
\param n borne max de l ensembl e

/
i nt bui l dBi j e c t i o n ( i nt n ) ;
/
getRandomInt
ret ourne un e nt i e r a l a t o i r e ent r e [ 0 , bSup ]
\param bSup l a borne sup de l i n t e r v a l l e

/
i nt getRandomInt ( i nt bSup ) ;
/
67
l s b
ret ourne l e l s b d un e nt i e r
\param n l e nt i e r

/
i nt l s b ( i nt n ) ;
public :
/
Const ruct eur
l e c t ur e du f i c h i e r
\param IMAGE_PATH l e chemin de l image s t eganogr aphi ee
\param STEGO_KEY mot de passe ne c e s s ai r e pour d f i n i r l e s marches a l a t o i r e s

/
Ext r act i on ( char IMAGE_PATH, i nt STEGO_KEY) ;
/
Des t ruct eur
/
~Ext r act i on ( ) ;
/
s huf f l e I mag e
m l a n g e l e s coef de l image
/
void s huf f l eI mage ( ) ;
/
s huf f l eMes s age
c r e at i on de l a b i j e c t i o n et de son i nv e r s e pour l e message
/
void s huf f l eMes s age ( ) ;
/
readParameters
l e c t ur e du p a r a m t r e de l al go et de l a t a i l l e du message
/
void readParameters ( ) ;
/
i ni t Paramet ers
i n i t i a l i s e l e s paramet res de l al go
/
void i ni t Par amet er s ( ) ;
/
ext ract Message
e x t r a i t l e message
/
void extractMessage ( ) ;
/
unShuf f l eMessage
68
remet l e message dans l e bon ordre
/
void unShuf f l eMessage ( ) ;
/
pri nt Message
a f f i c h e l e message e x t r a i t
/
void pri ntMessage ( ) ;
};
#endif
69
A.7 Extraction.cpp
/
Name : Ext r act i on
aut hor : R mi Watri gant
dat e : 30/04/09
Des cr i pt i on : e x t r a i t un message i n s r dans une image en u t i l i s a n t l al gor i t hme F5
de West f el d
/
#include " Ext r act i on . h"
#include <math . h>
#include <stdexcept >
/
Const ruct eur
l e c t ur e du f i c h i e r
\param IMAGE_PATH l e chemin de l image s t eganogr aphi ee
\param STEGO_KEY mot de passe ne c e s s ai r e pour d f i n i r l e s marches a l a t o i r e s

/
Ext r act i on : : Ext r act i on ( char IMAGE_PATH, i nt STEGO_KEY) {
this>stegoKey = STEGO_KEY;
// l e c t ur e du f i c h i e r . j pegLi ke accompagnant l e f i c h i e r . pgm
s t r i ng s t r Jpe gl i ke Pat h (IMAGE_PATH) ;
s t r Jpe gl i ke Pat h . e r as e ( s t r Jpe gl i ke Pat h . end() 4 , s t r Jpe gl i ke Pat h . end ( ) ) ;
s t r Jpe gl i ke Pat h += " . j pegLi ke " ;
i f s t r e am f i c h i e r ( s t r Jpe gl i ke Pat h . c_str ( ) , i o s : : i n ) ; // ouver t ur e en l e c t ur e
// s i l e f i c h i e r . j p e g l i k e e s t p r s e n t on l e l i t ,
// si non on a f f i c h e un message d erreur et on q u i t t e
i f ( f i c h i e r )
{
readFi l eAndFi l l LstDCT(& f i c h i e r ) ;
}
el se
{
c e r r << "Le f i c h i e r . j pegLi ke doi t accompagner l e f i c h i e r . pgm\n\tAbandon\n" ;
e xi t ( 1);
}
}
/
Des t ruct eur
/
Ext r act i on : : ~ Ext r act i on ( ) {
delete i mageBi j ect i on ;
delete i mage Bi j e c t i onI nve r s e ;
70
delete mes s ageBi j ect i on ;
delete me s s age Bi j e c t i onI nve r s e ;
for ( i nt i = 0 ; i < parameter_N ; i ++)
{
delete H[ i ] ;
}
delete H;
}
/
readFi l eAndFi l l LstDCT
l i t l e f i c h i e r et r e mpl i t l a l i s t e des coef DCT ai ns i que
l e s p a r a m t r e s de l al go se t r ouvant au debut du f i c h i e r
\param f i c h i e r f l u x i st ream
/
void Ext r act i on : : readFi l eAndFi l l LstDCT ( i f s t r e am f i c h i e r ) {
i nt compteur = 0;
vector <int> AC;
vector <int> DC;
s t r i ng l i g ne ;
while ( g e t l i ne ( f i c h i e r , l i g ne ) ) // t ant que l on peut met t re l a l i g ne dans l i g ne
{
i f ( ( compteur % 64) == 0)
{
DC. push_back ( at oi ( l i g ne . c_str ( ) ) ) ;
compteur++;
}
el se
{
AC. push_back ( at oi ( l i g ne . c_str ( ) ) ) ;
compteur++;
}
}
f i c h i e r >c l o s e ( ) ;
l s t Coe f . setAC(AC) ;
l s t Coe f . setDC(DC) ;
}
/
s huf f l eMes s age
m l a n g e l e s coef de l image
/
void Ext r act i on : : s huf f l eI mage ( ) {
srand ( stegoKey ) ;
i mageBi j ect i on = new i nt [ l s t Coe f . getNbAC ( ) ] ;
i mage Bi j e c t i onI nve r s e = new i nt [ l s t Coe f . getNbAC ( ) ] ;
i mageBi j ect i on = bui l dBi j e c t i o n ( l s t Coe f . getNbAC ( ) ) ;
71
vector <int> randomACCoef ;
randomACCoef . r e s i z e ( l s t Coe f . getNbAC ( ) ) ;
for ( i nt i = 0 ; i < l s t Coe f . getNbAC( ) ; i ++)
{
i mage Bi j e c t i onI nve r s e [ i mageBi j ect i on [ i ] ] = i ;
randomACCoef [ i ] = l s t Coe f . getIthAC( i mageBi j ect i on [ i ] ) ;
}
l s t Coe f . setAC( randomACCoef ) ;
}
/
s huf f l eMes s age
c r e at i on de l a b i j e c t i o n et de son i nv e r s e pour l e message
/
void Ext r act i on : : s huf f l eMes s age ( ) {
// c r a t i o n de l a b i j e c t i o n du message et son i nv e r s e
srand ( stegoKey ) ;
mes s ageBi j ect i on = new i nt [ message . s i z e ( ) ] ;
me s s age Bi j e c t i onI nve r s e = new i nt [ message . s i z e ( ) ] ;
mes s ageBi j ect i on = bui l dBi j e c t i o n ( message . s i z e ( ) ) ;
for ( i nt i = 0 ; i < message . s i z e ( ) ; i ++)
{
me s s age Bi j e c t i onI nve r s e [ mes s ageBi j ect i on [ i ] ] = i ;
}
}
/
readParameters
l e c t ur e du p a r a m t r e de l al go et de l a t a i l l e du message
/
void Ext r act i on : : readParameters ( ) {
vector <int> s_bi nary ;
vector <int> s i ze_bi nar y ;
for ( i nt i = 0 ; i < 32 ; i ++)
{
s_bi nary . push_back ( l s b ( l s t Coe f . getIthAC( i ) ) ) ;
s i ze_bi nar y . push_back ( l s b ( l s t Coe f . getIthAC( i +32) ) ) ;
}
parameter_S = 0;
s i zeMes s age = 0;
for ( i nt i = 0 ; i < 32 ; i ++)
72
{
parameter_S += s_bi nary [ i ] pow( 2 , 32i 1);
s i zeMes s age += s i ze_bi nar y [ i ] pow( 2 , 32i 1);
}
message . r e s i z e ( s i zeMes s age ) ;
/DEBUG/ /
cout << "Parametres i ns e r e s : " << endl ;
cout << "\ t Parametre s : " << parameter_S << endl ;
cout << "\ t Ta i l l e : " << message . s i z e ( ) << endl << endl ;
/DEBUG/
}
/
i ni t Paramet ers
i n i t i a l i s e l e s paramet res de l al go
/
void Ext r act i on : : i ni t Par amet er s ( ) {
parameter_N = ( i nt ) pow( 2 , parameter_S ) 1;
i ni t H ( ) ;
}
/
ext ract Message
e x t r a i t l e message
/
void Ext r act i on : : extractMessage ( ) {
i nt cpt = 64;
i nt cptMess = 0;
i nt buf f Coef = new i nt [ parameter_N ] ;
i nt messageBl oc = new i nt [ parameter_S ] ;
while ( cptMess < message . s i z e ( ) )
{
for ( i nt i = 0 ; i < parameter_N ; i ++)
{
buf f Coef [ i ] = l s b ( l s t Coe f . getIthAC( cpt ) ) ;
cpt = l s t Coe f . getIthNextNonZeroAC( cpt ) ;
}
messageBl oc = f or EachBl ocExt r act i on ( buf f Coef ) ;
for ( i nt i = 0 ; i < parameter_S ; i ++)
{
message [ cptMess ] = messageBl oc [ i ] ;
cptMess++;
73
}
}
}
/
f orEachBl ocExt ract i on
c a l c ul e l e syndrome d un bl oc , i e l e message qu i l c ont i e nt
\param supportRecu l e morceau de support
/
i nt Ext r act i on : : f or EachBl ocExt r act i on ( i nt supportRecu )
{
// c a l c u l du syndrome
i nt syndrome = new i nt [ parameter_S ] ;
for ( i nt i = 0 ; i < parameter_S ; i ++) syndrome [ i ] = 0;
for ( i nt i = 0 ; i < parameter_S ; i ++)
{
for ( i nt j = 0 ; j < parameter_N ; j ++)
{
syndrome [ i ] += ( supportRecu [ j ] H[ j ] [ i ] ) % 2 ;
}
syndrome [ i ] %= 2 ;
}
return syndrome ;
}
/
unShuf f l eMessage
remet l e message dans l e bon ordre
/
void Ext r act i on : : unShuf f l eMessage ( ) {
vector <int> newMessage ;
newMessage . r e s i z e ( message . s i z e ( ) ) ;
for ( i nt i = 0 ; i < message . s i z e ( ) ; i ++)
{
newMessage [ i ] = message [ me s s age Bi j e c t i onI nve r s e [ i ] ] ;
}
for ( i nt i = 0 ; i < message . s i z e ( ) ; i ++)
{
message [ i ] = newMessage [ i ] ;
}
/DEBUG/ /
cout << "Message non mel ange : " << endl ;
f or ( i nt i = 0 ; i < message . s i z e ( ) ; i ++)
{
cout << message [ i ] << " " ;
}
74
cout << endl ;
/DEBUG/
}
/
pri nt Message
a f f i c h e l e message e x t r a i t
/
void Ext r act i on : : pri ntMessage ( ) {
i nt ant i bour r age = message . s i z e ( ) ( message . s i z e ( ) / 8 ) 8 ;
/ DEBUG / /
i f ( ant i bour r age > 0)
{
cout << "Bourrage : " << ant i bour r age << endl ;
}
/ DEBUG /
char messageText = new char [ message . s i z e ( ) ant i bour r age ] ;
cout << endl << "MESSAGEEXTRAIT" << endl << endl ;
for ( i nt i = 0 ; i < message . s i z e ( ) / 8 ; i ++)
{
messageText [ i ] = 0;
for ( i nt j = 0 ; j < 8 ; j ++)
{
messageText [ i ] += message [ ant i bour r age+i 8 + j ] pow( 2 , 7j ) ;
}
cout << messageText [ i ] ;
}
cout << endl << endl << endl ;
}
/
i ni t H
i n i t i a l i s e l a mat ri ce H u t i l i s e dans l al go
p a r t i r du p a r a m t r e n et s

/
void Ext r act i on : : i ni t H ( ) {
H = new i nt [ parameter_N ] ; // mat ri ce H de 2^s 1 l i g ne s et s col onnes
for ( i nt i = 0 ; i < parameter_N ; i ++) // c ont i e nt t ous l e s e nt i e r s de 1 2^s 1 en b i nai r e sur l e s l i g ne s
{
H[ i ] = new i nt [ parameter_S ] ;
}
// c a l c u l de l a mat ri ce H
for ( i nt i = 0 ; i < parameter_N ; i ++)
75
{
convertIntToBi n ( i +1, H[ i ] , parameter_S ) ;
// f or ( i nt j = 0 ; j < parameter_S ; j ++) cout << H[ i ] [ j ] << " " ; cout << endl ;
}
}
/
convert Int ToBi n
c o nv e r t i t un nombre en un nombre en base 2
\param number l e nombre c onv e r t i r
\param bi nary p a r a m t r e d e n t r e / s o r t i e
\param s i z e l e nombre de b i t s sur l e s q u e l coder l e nombre

/
void Ext r act i on : : convertIntToBi n ( i nt number , i nt bi nary , i nt s i z e ) {
//On s t oc k e dans l e vect eur des poi ds f a i b l e s ver s l e s poi ds f o r t s .
for ( i nt i =0; i <s i z e ; i ++)
{
bi nary [ i ] = ( ( number>>i )&1);
i f ( ( bi nary [ i ] != 0) && ( bi nary [ i ] != 1) ) {
cout<<" convertIntToBi n : Converti onen bi na i r e n e s t pas bonne\n" ;
e xi t ( 1 ) ;
}
}
//on i nv e r s e l e t ab l e au
for ( i nt j = 0 ; j < s i z e /2 ; j ++)
{
i nt tmp = bi nary [ j ] ;
bi nary [ j ] = bi nary [ s i z e j 1] ;
bi nary [ s i z e j 1] = tmp;
}
}
/
b ui l d Bi j e c t i o n
c r une b i j e c t i o n de [ 1 , n] dans l u i m me
\param n borne max de l ensembl e

/
i nt Ext r act i on : : bui l dBi j e c t i o n ( i nt n) {
i nt i , j , nbelem ;
i nt f = new i nt [ n ] ;
vector <unsigned long int> l s t _i nt e ge r ( n ) ;
for ( i = 0 ; i < n ; i ++)
{
l s t _i nt e ge r [ i ] = i ;
76
}
i = 0;
for ( nbelem = n ; nbelem > 0 ; nbelem)
{
j = getRandomInt ( nbelem1);
f [ i ] = l s t _i nt e ge r [ j ] ;
l s t _i nt e ge r [ j ] = l s t _i nt e ge r [ nbelem1] ;
l s t _i nt e ge r . pop_back ( ) ;
i ++;
}
return f ;
}
/
getRandomInt
ret ourne un e nt i e r a l a t o i r e ent r e [ 0 , bSup ]
\param bSup l a borne sup de l i n t e r v a l l e

/
i nt Ext r act i on : : getRandomInt ( i nt bSup) {
i f ( bSup <= 0)
return 0;
el se
return ( i nt ) ( i nt ) r i nt ( bSup( rand ( ) /( double)RAND_MAX) ) ;
}
/
l s b
ret ourne l e l s b d un e nt i e r
\param n l e nt i e r

/
i nt Ext r act i on : : l s b ( i nt n) {
// p o s i t i f + i mpai r OU ne g a t i f + pai r => 1
// p o s i t i f + pai r OU ne g a t i f + i mpai r => 0
i f ( ( ( n > 0) && ( n%2 != 0) ) | | ( ( n < 0 ) && ( n%2 == 0) ) )
{
return 1;
}
el se
{
return 0;
}
}
77
A.8 mainEmbed.cpp
#i nc l ude "Embedding . h"
#include <c s t dl i b >
#include <c s t r i ng >
#include <s t di o . h>
#include <f stream>
#include <math . h>
#include <s t r i ng >
#include <i ostream>
using namespace std ;
/ PARAMETRES GLOBAUX DU PROGRAMME /
i nt STEGO_KEY ;
i nt QUALITY_FACTOR;
char STEGO_PATH;
char SUPPORT_PATH;
char MESSAGE_PATH;
char HISTO_PATH;
/ FONCTIONS PRIVEES NECESSAIRES /
void pr oces s Opt i ons I nLi ne ( int , char ) ;
/
MAIN
Programme p r i nc i p a l . . .

/
i nt main( i nt argc , char argv )
{
// t r a i t e l e s arguments du programme
pr oces s Opt i ons I nLi ne ( argc , argv ) ;
// cout << " i n i t i a l i s a t i o n . . . " << endl ;
// c ons t r uc t i on d une i ns t ance de l al go
Embedding embedding (SUPPORT_PATH, STEGO_PATH, MESSAGE_PATH, STEGO_KEY, QUALITY_FACTOR) ;
// cout << "compressi on . . . " << endl ;
// compressi on j us qu q u a nt i f i c a t i o n
embedding . compressi on ( ) ;
// cout << " c a l c u l c apac i t e . . . " << endl ;
// c a l c u l de l a t a i l l e du p a r a m t r e
// c a l c u l de l a t a i l l e du message dans l image s t e g a n o g r a p h i
embedding . computeCapaci ty ( ) ;
// cout << " m l a n g e du cover work . . . " << endl ;
// m l a n g e l e s b i t s du support
embedding . shuf f l eCoverWork ( ) ;
78
// cout << " m l a n g e du message . . . " << endl ;
// m l a n g e l e s b i t s du message ;
embedding . s huf f l eMes s age ( ) ;
// cout << " i ns e r t i o n de l a t a i l l e . . . " << endl ;
// i n s r e l a t a i l l e du p a r a m t r e et du message dans l e s premi ers p i x e l s
embedding . hi de Si z e s ( ) ;
// cout << " i ns e r t i o n du message . . . " << endl ;
// i n s r e l e message avec l a m t h o d e de mat ri x embedding
embedding . matrixEmbedding ( ) ;
// cout << " uns h uf f l e coverwork . . . " << endl ;
// r a r r a n g e l e coverWork
embedding . unShuffl eCoverWork ( ) ;
// cout << "decompresse et sauve l image . . . " << endl ;
// sauve l image s t eganogr aphi ee dans un . j pegLi ke
// sauve l image " d c o mp r e s s e " dans un . pgm
embedding . saveImage (STEGO_PATH) ;
i f ( argc == 7)
{
embedding . saveHi stogram (HISTO_PATH) ;
}
embedding . pr i nt Re s ul t s ( ) ;
return 0;
}
/
proccessOpt i onsI nLi ne
t r a i t e l e s opt i ons d e x c u t i o n
\param argc
\param argv

/
void pr oces s Opt i ons I nLi ne ( i nt argc , char argv )
{
i f ( ( argc != 6) && ( argc != 7) )
{
cout << "\nUsage : " << argv [ 0 ] << " support . pgm s t ego . pgmmessage . t xt stegoKey Qual i tyFact or [ hi s t o . dat ] \ n" ;
e xi t ( 1);
}
STEGO_PATH = new char [ 2 0 0 ] ;
SUPPORT_PATH = new char [ 2 0 0 ] ;
MESSAGE_PATH = new char [ 2 0 0 ] ;
// r ecopi e des p a r a m t r e s dans l e s v a r i a b l e s
s t r cpy (SUPPORT_PATH, argv [ 1 ] ) ;
79
s t r cpy (STEGO_PATH, argv [ 2 ] ) ;
s t r cpy (MESSAGE_PATH, argv [ 3 ] ) ;
char stegoKey = new char [ 2 0 0 ] ; s t r cpy ( stegoKey , argv [ 4 ] ) ;
STEGO_KEY = at oi ( stegoKey ) ;
char qual i t yFact or = new char [ 3 ] ; s t r cpy ( qual i t yFact or , argv [ 5 ] ) ;
QUALITY_FACTOR = at oi ( qual i t yFact or ) ;
i f ( argc == 7)
{
HISTO_PATH = new char [ 2 0 0 ] ;
s t r cpy (HISTO_PATH, argv [ 6 ] ) ;
}
}
80
A.9 mainExtract.cpp
#i nc l ude " Ext r act i on . h"
#include <c s t dl i b >
#include <c s t r i ng >
#include <s t di o . h>
#include <f stream>
#include <math . h>
#include <s t r i ng >
#include <i ostream>
using namespace std ;
/ PARAMETRES GLOBAUX DU PROGRAMME /
i nt STEGO_KEY;
char IMAGE_PATH;
/ FONCTIONS PRIVEES NECESSAIRES /
void pr oces s Opt i ons I nLi ne ( int , char ) ;
/
MAIN
Programme p r i nc i p a l . . .

/
i nt main( i nt argc , char argv )
{
// t r a i t e l e s arguments du programme
pr oces s Opt i ons I nLi ne ( argc , argv ) ;
// cout << " cons t r uct eur " << endl ;
// c ons t r uc t i on d une i ns t ance de l al go
Ext r act i on e xt r ac t i on (IMAGE_PATH, STEGO_KEY) ;
// cout << " s huf f l e I mag e ()" << endl ;
// m l a n g e l e s coef de l image
e xt r ac t i on . s huf f l eI mage ( ) ;
// cout << "readParameters ()" << endl ;
// l e c t ur e du p a r a m t r e de l al go et de l a t a i l l e du message
e xt r ac t i on . readParameters ( ) ;
// cout << " s huf f l eMes s age ( ) " << endl ;
// c r e at i on de l a b i j e c t i o n et de son i nv e r s e pour l e message
e xt r ac t i on . s huf f l eMes s age ( ) ;
// cout << " i ni t Paramet ers ()" << endl ;
// i n i t i a l i s e l e s p a r a m t r e s de l al go
e xt r ac t i on . i ni t Par amet er s ( ) ;
81
// cout << " ext ract Message ()" << endl ;
// e x t r a i t l e message
e xt r ac t i on . extractMessage ( ) ;
// cout << " uns huf f l eMes s age ( ) " << endl ;
//remet l e message dans l e bon ordre
e xt r ac t i on . unShuf f l eMessage ( ) ;
// cout << " pri nt Message ( ) " << endl ;
e xt r ac t i on . pri ntMessage ( ) ;
return 0;
}
/
proccessOpt i onsI nLi ne
t r a i t e l e s opt i ons d e x c u t i o n
\param argc
\param argv

/
void pr oces s Opt i ons I nLi ne ( i nt argc , char argv )
{
i f ( argc != 3)
{
cout << "\nUsage : " << argv [ 0 ] << "image . pgmstegoKey\n" ;
e xi t ( 1);
}
IMAGE_PATH = new char [ 2 0 0 ] ;
// r ecopi e des p a r a m t r e s dans l e s v a r i a b l e s
s t r cpy (IMAGE_PATH, argv [ 1 ] ) ;
char stegoKey = new char [ 2 0 0 ] ; s t r cpy ( stegoKey , argv [ 2 ] ) ;
STEGO_KEY = at oi ( stegoKey ) ;
}
82
A.10 attack.cpp
/
R m i Watri gant
09/05/2009
at t aque de l al gor i t hme F5
prend une image s t eganogr aphi ee en ent ree ,
suppri me l e s 4 premi eres et de r ni e r e s l i g ne s et col onnes ,
l u i appl i q ue un f i l t r e moyenneur
l a compresse
c a l c ul e son histogramme dct

/
#include " . . / image/image . H"
#include " . . / image/ i magei o . H"
#include " . . / image/ i maget ool s . H"
#include " . . / image/ dct . h"
#include <c s t dl i b >
#include <s t di o . h>
#include <c s t r i ng >
#include <f stream>
#include <math . h>
#include <s t r i ng >
#include <i ostream>
using namespace std ;
char IMAGE_PATH;
i nt QF;
/
proccessOpt i onsI nLi ne
t r a i t e l e s opt i ons d e x c u t i o n
\param argc
\param argv

/
void pr oces s Opt i ons I nLi ne ( i nt argc , char argv )
{
i f ( argc != 3)
{
cout << "\nUsage : " << argv [ 0 ] << "imagePath . pgm qual i t yFact or \n" ;
e xi t ( 1);
}
IMAGE_PATH = new char [ 2 0 0 ] ;
// r ecopi e des p a r a m t r e s dans l e s v a r i a b l e s
s t r cpy (IMAGE_PATH, argv [ 1 ] ) ;
char qual i t yFact or = new char [ 3 ] ; s t r cpy ( qual i t yFact or , argv [ 2 ] ) ;
QF = at oi ( qual i t yFact or ) ;
83
}
/
crop ( )
suppri me l e s 4 premi eres et de r ni e r e s l i g ne s et col onnes d une image

/
Image<oct et > crop ( Image<oct et > i mageIn )
{
i nt wi dth = imageIn>NbCol ( ) ;
i nt hei ght = imageIn>NbRow( ) ;
Image<oct et > newImage = new Image<oct et >( hei ght 8, width 8);
for ( i nt i = 0 ; i < width8 ; i ++)
{
for ( i nt j = 1 ; j < hei ght 8 ; j ++)
{
( newImage ) [ j ( width 8) + i ] = ( i nt ) ( i mageIn ) [ ( j +4)wi dth + ( i +4) ] ;
}
}
/TEST/ /
ImageIO<oct et >: : WritePGM(" i mages /cropped . pgm" , newImage ) ;
/TEST/
return newImage ;
}
/
f i l t r e ( )
e f f e c t u e un f i l t e moyenneur sur l image en e n t r e

/
Image<oct et > f i l t r e ( Image<oct et > i mageIn )
{
i nt wi dth = imageIn>NbCol ( ) ;
i nt hei ght = imageIn>NbRow( ) ;
i nt t a i l l e F i l t r e = 3;
// t rans f ormat i on de l image dans un t ab l e au 2D
i nt _imgIn [ wi dth ] [ hei ght ] ;
double _imgOut [ wi dth ] [ hei ght ] ;
for ( i nt i = 0 ; i < wi dth ; i ++)
{
for ( i nt j = 0 ; j < hei ght ; j ++)
{
_imgIn [ i ] [ j ] = ( i nt ) ( i mageIn ) [ j wi dth + i ] ;
_imgOut [ i ] [ j ] = 0;
}
84
}
double paramFi l tre = 2;
// f i l t r a g e
for ( i nt i = t a i l l e F i l t r e /2 ; i < widtht a i l l e F i l t r e /2 ; i ++)
{
for ( i nt j = t a i l l e F i l t r e /2 ; j < hei ght t a i l l e F i l t r e /2 ; j ++)
{
_imgOut [ i ] [ j ] = ( 1/( 4 paramFi l t re ) ) ( paramFi l tre _imgIn [ i 1] [ j ]+paramFi l tre _imgIn [ i +1] [ j ]+paramFi l t re _imgIn [ i ] [ j 1]+paramFi l t re _imgIn [ i ] [ j +1] ) ;
}
}
// t r ans f or mat i on du t ab l e au 2D en image de s o r t i e
Image<oct et > newImage = new Image<oct et >( hei ght , wi dth ) ;
for ( i nt i = 0 ; i < wi dth ; i ++)
{
for ( i nt j = 0 ; j < hei ght ; j ++)
{
( newImage ) [ j wi dth+i ] = ( i nt ) round ( _imgOut [ i ] [ j ] ) ;
}
}
/TEST/ /
ImageIO<oct et >: : WritePGM(" i mages / t e s t . pgm" , newImage ) ;
/TEST/
return newImage ;
}
/
readJpegLi keAndFi l l Hi s t o
l i t l e f i c h i e r j pegLi ke qui c ont i e nt l a l i s t e des coef DCT de l image s t eganogr aphi ee
param h i s t o l h i s t o r empl i r
/
void r eadJpegLi keAndFi l l Hi st o (map<int , int> hi s t o [ 8 ] [ 8 ] )
{
//on t ransf orme l e char . pgm en un s t r i ng . j p e g l i k e
s t r i ng j pegLi kePath (IMAGE_PATH) ;
j pegLi kePath . e r as e ( j pegLi kePath . end() 4 , j pegLi kePath . end ( ) ) ;
j pegLi kePath += " . j pegLi ke " ;
i f s t r e am f i l e ( j pegLi kePath . c_str ( ) , i o s : : i n ) ;
i f ( f i l e )
{
char car ;
i nt c oe f ;
i nt compteur = 0;
while ( ! f i l e . e of ( ) )
{
85
f i l e . g e t l i ne ( car , 256) ;
c oe f = at oi ( car ) ;
i nt numeroLigne = ( compteur /8) % 8;
i nt numeroColonne = compteur % 8;
// cout << compteur << " => (" << numeroLigne << " , " << numeroColonne << ") : " << coef << endl ;
hi s t o [ numeroLigne ] [ numeroColonne ] [ c oe f ] = hi s t o [ numeroLigne ] [ numeroColonne ] [ c oe f ] + 1;
compteur++;
}
}
el se
{
c e r r << "Le f i c h i e r . j pegLi ke doi t accompagner l e f i c h i e r . pgm\n\tAbandon\n" ;
e xi t ( 1);
}
}
/
compressAndBui l dEst i mat edHi st o
compresse l image c r o p e f i l t r e et c a l c ul e l e s hi stogrammes i nd i v i d u e l s
\param imageIn l image c r o p e f i l t r e
\param h i s t o l h i s t o rempl i r
/
void compressAndBui l dEsti matedHi sto ( Image<oct et > imageIn , map<int , int> hi s t o [ 8 ] [ 8 ] )
{
i nt hei ght = imageIn>NbRow( ) ;
i nt wi dth = imageIn>NbCol ( ) ;
// c ons t r uc t i on de l a t a b l e de q u a nt i f i c a t i o n
i nt tabRef [ 8 8 ] = { 16 , 11 , 10 , 16 , 24 , 40 , 51 ,
61 ,
12 , 12 , 14 , 19 , 26 , 58 ,
60 , 55 ,
14 , 13 , 16 , 24 , 40 , 57 , 69 , 56 ,
14 , 17 , 22 , 29 , 51 , 87 ,
80 , 62 ,
18 , 22 , 37 , 56 , 68 , 109 , 103 , 77 ,
24 , 35 , 55 , 64 , 81 , 104 , 113 , 92 ,
49 , 64 , 78 , 87 , 103 , 121 , 120 , 101 ,
72 , 92 , 95 , 98 , 112 , 100 , 103 , 99 };
// p a r a m t r e c (Q)
double cQ;
i f (QF < 50)
{
cQ = 50000/(QF+1);
}
el se
{
cQ = 200 2QF;
86
}
double tabQuant = new double [ 8 8 ] ;
for ( i nt i = 0 ; i < 88 ; i ++)
{
tabQuant [ i ] = tabRef [ i ] cQ/100 ;
}
for ( i nt row = 0 ; row < hei ght /8 ; row++)
{
for ( i nt c ol = 0 ; c ol < wi dth/8 ; c ol ++)
{
// premi er lement du b l oc
i nt i 0 = row8 wi dth+c ol 8;
// r empl i s s age des coef
double bl oc = new double [ 8 8 ] ;
for ( i nt x = 0; x < 8 ; x++)
{
for ( i nt y = 0 ; y < 8 ; y++)
{
bl oc [ 8 y+x ] = ( i mageIn ) [ i 0+ywi dth+x ] ;
}
}
// dct convers i on
dct : : Data2DCT88( bl oc ) ;
// Di vi s i on
for ( i nt x = 0; x < 8 ; x++)
{
for ( i nt y = 0 ; y < 8 ; y++)
{
bl oc [ 8 y+x ] = round ( bl oc [ 8 y+x ] / tabQuant [ 8 y+x ] ) ;
hi s t o [ x ] [ y ] [ round ( bl oc [ 8 y+x ] ) ] = hi s t o [ x ] [ y ] [ round ( bl oc [ 8 y+x ] ) ] + 1;
}
}
}
}
}
/
f i l l Be t a _k l
rempl i l e t ab l e au des bet a
\param H l h i s t o de l a s t e g o image
\param hbarre l h i s t o de l image est i mee
/
void f i l l Be t a _kl (map<int , int> H[ 8 ] [ 8 ] , map<int , int> hbarre [ 8 ] [ 8 ] , double beta_kl [ 8 ] [ 8 ] )
{
87
for ( i nt k = 0 ; k < 8 ; k++)
{
for ( i nt l = 0 ; l < 8 ; l ++)
{
double hbarre_0 = hbarre [ k ] [ l ] [ 0 ] ;
double hbarre_1 = hbarre [ k ] [ l ] [ 1 ] + hbarre [ k ] [ l ] [ 1 ] ;
double hbarre_2 = hbarre [ k ] [ l ] [ 2 ] + hbarre [ k ] [ l ] [ 2 ] ;
double H_0 = H[ k ] [ l ] [ 0 ] ;
double H_1 = H[ k ] [ l ] [ 1 ] + H[ k ] [ l ] [ 1 ] ;
double H_2 = H[ k ] [ l ] [ 2 ] + H[ k ] [ l ] [ 2 ] ;
beta_kl [ k ] [ l ] = ( hbarre_1 ( H_0 hbarre_0 ) + ( H_1 hbarre_1 )
( hbarre_2 hbarre_1 ) ) / ( ( hbarre_1 hbarre_1 ) + ( hbarre_2 hbarre_1 ) ( hbarre_2 hbarre_1 ) ) ;
}
}
}
/
computeBeta
c a l c ul e bet a a p a r t i r des bet a_kl
\param bet a_kl
/
double computeBeta ( double beta_kl [ 8 ] [ 8 ] )
{
/
cout << " bet a [ 0 ] [ 1 ] = " << bet a_kl [ 0 ] [ 1 ] << endl ;
cout << " bet a [ 1 ] [ 0 ] = " << bet a_kl [ 1 ] [ 0 ] << endl ;
cout << " bet a [ 1 ] [ 1 ] = " << bet a_kl [ 1 ] [ 1 ] << endl ;
/
return ( ( beta_kl [ 0 ] [ 1 ] + beta_kl [ 1 ] [ 0 ] + beta_kl [ 1 ] [ 1 ] ) / 3 ) ;
}
/
computeLongueurMessage
c a l c ul e l a l ongueur du message i ns e r e
\param bet a p r o b a b i l i t e de modi f i cat i on d un coef AC != 0
\param es t i mat edHi s t o l histogramme de l image est i mee
/
i nt computeLongueurMessage ( double beta , map<int , int> es t i mat edHi s t o [ 8 ] [ 8 ] )
{
i nt nb_usabl e_coef = 0; //nombre de coef AC non nul
i nt coef Egal 1 = 0;
i nt k = 0; // parametre de l al go t a i l l e des b l oc s de message
i nt l ongueur_message = 0;
//CALCUL DE NB_USABLE_COEF et de Coef Egal 1
for ( i nt k = 0 ; k < 8 ; k++)
{
for ( i nt l = 0 ; l < 8 ; l ++)
{
i f ( k+l >= 1 )
88
{
for (map<int , int >: : i t e r a t o r i t = es t i mat edHi s t o [ k ] [ l ] . begi n ( ) ; i t != es t i mat edHi s t o [ k ] [ l ] . end ( ) ; i t ++)
{
i f ( ( ( i t ) . f i r s t == 1) | | ( ( i t ) . f i r s t == 1) )
coef Egal 1 += ( i t ) . second ;
i f ( ( i t ) . f i r s t != 0)
nb_usabl e_coef += ( i t ) . second ;
}
}
}
}
//CALCUL DU PARAMETRE K
k = round ( l og ( ( 1 / beta ) + 1 ) / l og ( 2) ) ;
i nt capaci t y = round ( nb_usabl e_coef 0. 51 coef Egal 1 ) ;
//CALCUL DE LA LONGUEUR DU MESSAGE
l ongueur_message = (pow( 2 , k ) /( pow( 2 , k) 1 ) ) k beta capaci t y ;
return l ongueur_message ;
}
i nt main( i nt argc , char argv )
{
// t r a i t e l e s arguments du programme
pr oces s Opt i ons I nLi ne ( argc , argv ) ;
//LECTURE DE LIMAGE DENTREE
Image<oct et > i mageIn = new Image<oct et >();
ImageIO<oct et >: :ReadPGM(IMAGE_PATH, i mageIn ) ;
Image<oct et > cropped = crop ( i mageIn ) ;
Image<oct et > f i l t r e e = f i l t r e ( cropped ) ;
// l e s hi stogrammes i nd i v i d u e l s
map<int , int> es t i mat edHi s t o [ 8 ] [ 8 ] ;
map<int , int> s t egoHi s t o [ 8 ] [ 8 ] ;
double beta_kl [ 8 ] [ 8 ] ;
double beta ;
r eadJpegLi keAndFi l l Hi s t o ( s t egoHi s t o ) ;
compressAndBui l dEsti matedHi sto ( f i l t r e e , es t i mat edHi s t o ) ;
f i l l Be t a _kl ( s t egoHi s t o , est i mat edHi st o , beta_kl ) ;
beta = computeBeta ( beta_kl ) ;
cout << " beta =" << beta << endl ;
i nt l ongueurMessage = computeLongueurMessage ( beta , es t i mat edHi s t o ) ;
cout << " l ongueur dumessage =" << l ongueurMessage << endl ;
89
return 0;
}
90
A.11 makele
# I ndi quer quel compi l at eur e s t a u t i l i s e r
CPP=g++
# S p e c i f i e r l e s opt i ons du compi l at eur
CFLAGS=
LDFLAGS=
#Nom de l execut abl e
EXEC1 = compress
EXEC2 = embed
EXEC3 = e xt r ac t
EXEC4 = at t ack
# Li s t e de f i c h i e r s obj e t s ne c e s s a i r e s pour l e programme f i n a l
#SRC = f i c h i e r . cc f i c h i e r 1 . cc f i c h i e r 2 . cc
OBJ1 = . / s r c / compressi on/compress . o . / s r c /image/ dct . o
OBJ2 = . / s r c /F5/Embedding . o . / s r c /image/ dct . o . / s r c /F5/mainEmbed . o . / s r c /image/DCTCoef . o
OBJ3 = . / s r c /F5/ Ext r act i on . o . / s r c /F5/mai nExtract . o . / s r c /image/DCTCoef . o
OBJ4 = . / s r c /F5/ at t ack . o . / s r c /image/ dct . o
a l l : $ (EXEC1) $ (EXEC2) $ (EXEC3) $ (EXEC4)
# Creati on des . o a pa r t i r des . cc
%.o : %. c
$ (CPP) $<
# Generati on du f i c h i e r execut abl e
$ (EXEC1) : $ (OBJ1)
# Deuxieme p o s s i b i l i t e ATTENTION : OBJ contenant pl us i e ur s
# dependances , i l f aut u t i l i s e r $^ et non $<
$ (CPP) o $@ $^
$ (EXEC2) : $ (OBJ2)
# Deuxieme p o s s i b i l i t e ATTENTION : OBJ contenant pl us i e ur s
# dependances , i l f aut u t i l i s e r $^ et non $<
$ (CPP) o $@ $^
$ (EXEC3) : $ (OBJ3)
# Deuxieme p o s s i b i l i t e ATTENTION : OBJ contenant pl us i e ur s
# dependances , i l f aut u t i l i s e r $^ et non $<
$ (CPP) o $@ $^
$ (EXEC4) : $ (OBJ4)
# Deuxieme p o s s i b i l i t e ATTENTION : OBJ contenant pl us i e ur s
# dependances , i l f aut u t i l i s e r $^ et non $<
$ (CPP) o $@ $^
91
.PHONY : cl ean mrproper
# Nettoyage
cl ean :
rm r f . o
rm r f . ~
rm r f ~
mrproper : cl ean
rm r f $ (EXE1) . exe
rm r f $ (EXE2) . exe
rm r f $ (EXE3) . exe
rm r f $ (EXE4) . exe
92

You might also like