dimanche 30 janvier 2011

Least Significant Bit ou LSB

Introduction

Une technique fréquemment utilisée en stéganographie pour cacher des informations est la technique du Least Significant Bit, LSB ou bits de poids faible. Contrairement à mon article sur le padding BMP, cette méthode peut être utilisée sur plusieurs formats d'images, tant que celui-ci n'utilise pas de compression avec perte. Il est donc possible de l'utiliser sur les formats BMP, PNG, GIFF... mais ne pourra pas être appliquée au format JPG. L'objectif du LSB est de modifier de façon imperceptible l'image pour cacher de l'information.

Principe

Pour commencer il est nécessaire de comprendre comment sont stockées les informations dans une image. Chaque image est constituée de pixels codés généralement par 3 couleurs : rouge, vert et bleu (RGB). Chaque pixel représente donc une certaine quantité de rouge, une certaine quantité de vert et une certaine quantité de bleue.
Si on prend le cas ou chaque couleur de chaque pixel est codée sur un octet il y a donc 256 valeurs pour une couleur de 0 (la couleur n'est pas présente) à 255.

On peut donc représenter 256^3 soit 16777216 couleurs au total. L'idée est que l'œil humain ne va pas être capable de distinguer parfaitement toutes ces couleurs et que donc de légères modifications sur la couleur des pixels ne seront pas distinguables en tout cas pour l'œil humain.

Prenons un exemple, la couleur suivante est constituée uniquement de rouge et a la valeur 255,0,0 (255 de rouge, 0 de vert et 0 de bleu), la suivante a la valeur 254,0,0.

Comme on peut le voir la différence est difficilement visible. L'image suivante contient les couleurs suivantes sur la première ligne 255,0,0 0,255,0 0,0,255 et sur la deuxième ligne les couleurs suivantes 254,0,0 0,254,0 0,0,254.

Représentation binaire

Le but est donc de trouver un moyen d'altérer la couleur de l'image d'une façon imperceptible. Cette technique va se baser sur la représentation du nombre en binaire. Comme dit précédemment, une couleur est codée sur un octet, soit 8 bits. On peut donc représenter n'importe quelle couleur par une suite de 8 bits. Ce qui est intéressant dans cette approche c'est que chaque bit n'est pas porteur de la même quantité d'information. Le bit de poids faible (le bit le plus à droite) a un poids de 1, c'est à dire que le fait qu'il soit à 1 ou à 0 ne modifiera la valeur finale que de 1, alors que le bit de poids fort (le bit le plus à gauche) a un poids de 128.

Le tableau suivant détaille le poids de chaque bit :

Représentation binaire de 153 = 10011001b


bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
Valeur binaire10011001
Poids du bit1286432168421

Pour vérifier : 153 = 1*128 + 0*64 + 0*32 + 1*16 + 1*8 + 0*4 + 0*2 + 1*1

L'idée finale est donc d'altérer les bits qui portent le moins d'informations pour y stocker notre message caché. Etant donné que ces bits sont porteurs de peu d'information, l'aspect visuel de l'image sera peu altéré.

Cacher de l'information

Prenons un exemple concret où nous voulons cacher la lettre "A" dans 3 pixels. Les 3 pixels seront 153,74,186 255,255,255 0,0,0. La lettre "A" a la valeur ASCII 65 soit 01000001b en binaire. Comme dit précédemment, on va modifier les bits de poids faible de chaque couleur pour stocker notre information.

Pixel 1 RougePixel 1 VertPixel 1 BleuPixel 2 RougePixel 2 VertPixel 2 BleuPixel 3 RougePixel 3 VertPixel 3 Bleu
Valeur Décimale15374186255255255000
Valeur Binaire100110010100101010111011111111111111111111111111000000000000000000000000
Bit à cacher01000001padding
Couleur finale binaire100110000100101110111010111111101111111011111110000000000000000100000000
Couleur finale15275186254254254010


La nouvelle suite de couleur passe à 152,75,186 254,254,254 0,1,0. Comme on peut donc le voir, une légère modification a lieu.

Pour aller plus loin

L'exemple ici porte sur la façon de cacher de l'information dans le bit 0, celui qui est porteur du moins grand nombre d'informations. Il est toutefois possible d'utiliser plusieurs bits comme par exemple les bits 0, 1 et 2. L'image sera au final altérée de façon plus importante, mais la quantité d'information cachée sera plus grande. En stégagnographie tout est question de compromis : Plus on cachera d'information et plus on détériorera le support et donc plus il sera facile de déceler qu'une information est cachée.

Exemple d'information cachée

L'image suivante possède une information cachée dans ses bits de poids de faible. Ici contrairement au padding BMP, aucune chance de ne voir quoique ce soit en ouvrant l'image dans un editeur hexa ;)

6 commentaires:

  1. Bien joué pour la série d'articles sur la stégano, j'ai jamais réellement trouvé d'infos dans ce domaine là sur Internet (soit elles sont bien cachées, soit je suis une bille, au choix), mais je trouve ça bien d'expliquer quelques techniques :)

    J'essaierais de pondre un article ou deux là dessus, une fois que j'aurais fini la Webapp 8 de a NdH

    Enjoy

    The lsd

    RépondreSupprimer
  2. Clair et bien expliqué pour des débutants comme moi en stégano.
    N'hésite pas à faire de nouveaux articles comme cette série d'articles sur la stégano.
    Shp

    RépondreSupprimer
  3. "L'image suivante possède une information cachée dans ses bits de poids de faible"


    Je souhaiterais volontiers avoir plus d'info dessus, car j'ai retourné l'image dans tous les sens et je ne vois rien! D'ailleurs, statistiquement, l'image ne semble pas cacher d'information sur ses bits de poids faible(peu de "bruit")

    Est-ce une erreur de ma part ou bien l'image n'est pas cache effectivement rien?

    RépondreSupprimer
  4. @keutru
    Je me réponds à moi même, y'a effectivement du bruit sur l'image pouvant caractériser une information cachée. Je n'le voyais pas initialemement à cause du fonctionnement plutôt surprenant d'image magick(via Perl), les valeures RGB obtenues via les fonctions Image::Magick::GetPixel sont en fait les valeurs RGB originales multipliées par 257.... Allez comprendre...

    Je n'ai toujours pas trouvé ce que cachait cette image et donc les complément d'infos sont toujours les bienvenus!

    RépondreSupprimer
  5. Normalement ce n'est pas compliqué :) Tu prends les derniers bits de chaque composante de chaque pixel et tu mets tout ça dans un fichier. Ne t'attends pas à trouver une phrase compréhensible ;)
    N'hésites pas à me dire si tu ne trouves toujours pas.

    RépondreSupprimer
  6. @time0ut
    Merci pour ta réponse.

    J'ai retenté ma chance et pfiou! C'est bon :):), mais ce fut laborieux! Après la surprise du facteur 257 pour Image::Magick, j'en avais oublié de retester les choses simples, j'étais parti à parcourir les pixels dans un sens ou dans un autre, à considérer que finalement (d'après l'article) il y avait vraiment un bit de padding chaque 3 pixels, ou encore que les bits récupérés étaient donné dans l'ordre LSB Firstaulieu de MSBF!

    Pour ceux cherchant encore: faites simple!

    Note: pour ceux travaillant avec GD (et Perl en tout cas), n'oubliez pas d'activer les 'TrueColors' à l'ouverture de votre image, et pour ceux travaillage avec Image::Magick voyez mon commentaire ci-dessus.

    RépondreSupprimer