Projet ISN 1

Stéganographie

Frédérique Beaudeux

Sommaire

  1. Introduction
  2. Stéganographie spatiale VS stéganographie fréquentielle
  3. Format Jpeg
  4. Stéganographie fréquentielle
  5. Conclusion

Introduction

  • Stéganographie
  • Cryptographie
  • Watermarking


Site du projet
Stéganographie spatiale
VS
stéganographie fréquentielle


  • Différences entre les deux méthodes
  • Avantage de la stéganographie fréquentielle

Le format Jpeg



Cette partie va expliquer les différentes étapes de la compression d'images JPEG

Transformation des couleurs RVB en Luminance Chrominance
def luminance_chrominance(image):
	largeur_m,hauteur_m=image.size
	matrice=[[[0,0,0] for i in range(0,hauteur_m)]for j in range(0,largeur_m)]
	mat=[[0 for i in range(hauteur_m)] for j in range(largeur_m)]
	for x in range(0,largeur_m):
		for y in range(0,hauteur_m):
			pixel=image.getpixel((x,y))
			L=(0.299*pixel[0]+0.587*pixel[1]+0.114*pixel[2])
			Cb=(-0.168736*pixel[0]-0.331264*pixel[1]+0.5*pixel[2])+128
			Cr=(0.5*pixel[0]-0.418688*pixel[1]-0.081312*pixel[2])+128
			matrice[x][y]=[L,Cb,Cr]
			mat[x][y]=L
	return matrice,mat

Sous-échantillonnage

Découpage en bloc 8x8

On découpe la matrice de luminance en matrices 8x8 et on complete par des zéros si les dimensions ne sont pas divisibles par 8

Calculs des coefficients DCT
def DCT(matrice):
    matrice_DCT=[[0 for i in range(8)]for j in range(8)]
    for x in range(8):
        for y in range(8):
            dct=0.0
            for i in range(8):
                for j in range(8):
                    dct=dct+matrice[i][j]*cos((2*i+1)*x*pi/16)*cos((2*j+1)*y*pi/16)
            if x==0 :
                cx=1/sqrt(2)
            else :
                cx=1
            if y==0 :
                cy=1/sqrt(2)
            else :
                cy=1
            dct=(dct*1/4*cx*cy)
            matrice_DCT[x][y]=dct
    return matrice_DCT
Quantification

On divise tous les coefficients de la matrice DCT par les coefficients de la matrice de quantification
et on obtient la matrice quantifiée :

Codage RLE

En appliquant ce type de lecture sur la matrice quantifiée, on obtient la liste de coefficients :
Zig-zag=[79,0,-2,-1,-1,-1,0,0,-1] le reste étant une suite de 0

Codage de Huffman

  • algorithme de compression de données sans perte.
  • code à longueur variable dépendant de la fréquence d'apparition de la valeur à coder
  • code court étant associé aux symboles de source les plus fréquents.

Stéganographie fréquentielle

Encodage du message
Explications
def cache(mat_dct,fichier):
    global liste
    rang,x,y=0,0,0
    with open(fichier,'r') as f: 
        message=f.read()
    taille=len(message)
    tailleBin=bin(taille).lstrip('0b').zfill(8)
    for i in range(8):
        while (mat_dct[rang][y][x])>=0 or (mat_dct[rang][y][x])<=-100 or (x,y,rang) in liste:
            if x==7 and (x,y)!=(7,7):
                x,y=0,y+1
            elif (x,y)==(7,7):
                rang+=1
                x,y=0,0
            else:
                x+=1
        if (tailleBin[i]=='0' and int(mat_dct[rang][y][x]/10)%2==1) or (tailleBin[i]=='1' and \
		int(mat_dct[rang][y][x]/10)%2==0):
            mat_dct[rang][y][x]=int(mat_dct[rang][y][x]/10)*10-15
        else:
            mat_dct[rang][y][x]=int(mat_dct[rang][y][x]/10)*10-5
DCT inverse
def DCT_inv(mat_dct):
    matrice_DCTinv=[[0 for i in range(8)]for j in range(8)]
    for i in range(8):
        for j in range(8):
            dct_inv=0.0
            for u in range(8):
                for v in range(8):
                    if u==0 :
                        cu=1/sqrt(2)
                    else :
                        cu=1
                    if v==0 :
                        cv=1/sqrt(2)
                    else :
                        cv=1
                    dct_inv=dct_inv+cu*cv*mat_dct[u][v]*cos((2*i+1)*u*pi/16)*cos((2*j+1)*v*pi/16)
            
            dct_inv=(dct_inv*1/4)
            matrice_DCTinv[i][j]=dct_inv
    return matrice_DCTinv
reconstitution de la nouvelle image stéganographiée
def mat_RVB(mat_lum,matrice_LCbCr,image):
    largeur_m,hauteur_m=image.size
    imgstega=image.copy()
    for x in range(0,largeur_m):
        for y in range(0,hauteur_m):            
            R=round(1*mat_lum[x][y]-0.0*(matrice_LCbCr[x][y][1]-128)+1.402*(matrice_LCbCr[x][y][2]-128))
            V=round(1*mat_lum[x][y]-0.344136*(matrice_LCbCr[x][y][1]-128)-0.714136*(matrice_LCbCr[x][y][2]-128))
            B=round(1*mat_lum[x][y]+1.772*(matrice_LCbCr[x][y][1]-128)-0.0*(matrice_LCbCr[x][y][2]-128))
            imgstega.putpixel((x,y),(R,V,B))#recalcule les nouveaux pixels de la nouvelle image stéganographiée
    imgstega.show()
    return imgstega
Decodage du message
def retrouveMessage(mat_dct): 
    global liste
    rang,x,y=0,0,0
    c=''
    taillebin=''
    for i in range(8):
        while (mat_dct[rang][y][x])>=0 or (mat_dct[rang][y][x])<=-100 or (x,y,rang) in liste : 
            if x==7 and (x,y)!=(7,7):
                x,y=0,y+1
            elif (x,y)==(7,7):
                rang+=1
                x,y=0,0
            else:
                x+=1
        if  int(mat_dct[rang][y][x]/10)%2==1 :
            taillebin+='1' 
        else:
            taillebin+='0'
        if x==7 and (x,y)!=(7,7):
            x,y=0,y+1
        elif (x,y)==(7,7):
            rang+=1
            x,y=0,0
        else:
            x+=1
    rang+=1
    tailleMessage=int(taillebin,2)  
    for j in range(tailleMessage):
        taillebin=''
        for i in range(8):
            while (mat_dct[rang][y][x])>=0 or (mat_dct[rang][y][x])<=-100 or (x,y,rang) in liste : 
                if x==7 and (x,y)!=(7,7):
                    x,y=0,y+1
                elif (x,y)==(7,7):
                    rang+=1
                    x,y=0,0
                else:
                    x+=1
            if  int(mat_dct[rang][y][x]/10)%2==1 :
                taillebin+='1'
            else:
                taillebin+='0'
            if x==7 and (x,y)!=(7,7):
                x,y=0,y+1
            elif (x,y)==(7,7):
                rang+=1
                x,y=0,0
            else:
                x+=1
        asci_car=int(taillebin,2)
        c+=chr(asci_car)
        rang+=1
    return c

Taille du message secret codé en premier sur 8 bits ,
donc taille maximale : 2^8=256 caractères

Interface Graphique
def encodage(): #encoder en ouvrant l'explorateur de fichier windows pour localiser les fichiers
    global main
    main.conteneurname =  filedialog.askopenfilename(initialdir = "/",title = "Sélectionnez l'image conteneur",\
    filetypes = (("jpg files","*.jpg"),("all files","*.*")))
    main.secretname =  filedialog.askopenfilename(initialdir = "/",title = "Sélectionnez le fichier avec le texte secret",\
    filetypes = (("txt files","*.txt"),("all files","*.*")))
    imagesecrete=Encode(main.secretname,main.conteneurname)
    imageName=save()
    imagesecrete.save(imageName,type="JPG")

Conclusion

  • Notions découvertes
  • Problèmes rencontrés