Professional Documents
Culture Documents
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
_
_
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
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
/
vector <int> getAC ( ) ;
/
/
vector <int> getDC ( ) ;
/
/
void setAC( vector <int> AC) ;
/
/
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 ] ) ;
}
}
/
/
vector <int> DCTCoef : : getAC( ) {
return AC;
}
35
/
/
vector <int> DCTCoef : : getDC( ) {
return DC;
}
/
/
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 ] ) ;
}
}
/
/
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