You are on page 1of 95

Calhoun: The NPS Institutional Archive

Theses and Dissertations

Thesis Collection

1996-03

Implementation and efficiency of steganographic


techniques in bitmapped images and embedded
data survivability against lossy compression schemes
Currie, Daniel L.
Monterey, California. Naval Postgraduate School
http://hdl.handle.net/10945/8501

NAVAL POSTGRADUATE SCHOOL


Monterey, California

THESIS
IMPLEMENTATION AND EFFICIENCY OF STEGANOGRAPHIC TECHNIQUES IN BITMAPPED IMAGES AND
EMBEDDED DATA SURVIVABILITY AGAINST LOSSY
COMPRESSION SCHEMES
by
Daniel L. Currie,

III

Hannelore Campbell

March 1996
Thesis Advisors:

Approved

Thesis
C9565

Cynthia E. Irvine
Harold Fredricksen

for public release; distribution

is

unlimited.

DUDLEY KNOX LIBRARY


GRADUATE SCHOOL
MC
CA 93&4^5101
:

Form Approved

REPORT DOCUMENTATION PAGE


Public reporting burden for this collection of information

is

estimated to average

OMB No.

0704-0188

hour per response, including the time reviewing instructors searching existing data sources

gathering and maintaining the data needed, and completing and reviewing the collection of information

Send comments regarding this burden estimate or any other aspect of this
Washington Headquarters Services Directorate for Information Operations and Reports 1215 Jefferson
the Office of Management and Budget. Paperwork Reduction Project (07040188) Washington DC 20503

collection of information, including suggestions for reducing this

Davis Highway, Suite 1204. Arlington,


1.

VA 22202-4302. and to

AGENCY USE ONLY (Leave Blank)

2.

burden

to

REPORT DATE

3.

March 1996
TITLE

4.

REPORT TYPE AND DATES COVERED


Master's Thesis

AND SUBTITLE

5.

IMPLEMENTATION AND EFFICIENCY OF STEGANOGRAPHIC


TECHNIQUES IN BITMAPPED IMAGES AND EMBEDDED DATA
SURVIVABILITY AGAINST LOSSY COMPRESSION SCHEMES

FUNDING NUMBERS

AUTHOR(S)

6.

Currie, Daniel

III

Campbell, Hannelore
PERFORMING ORGANIZATION NAME(S) AND ADDRESS(ES)

7.

8.

Naval Postgraduate School


Monterey,

9.

PERFORMING ORGANIZATION
REPORT NUMBER

CA 93943-5000

SPONSORING/ MONITORING AGENCY NAME(S) AND ADDRESS(ES)

10.

SPONSORING/ MONITORING

AGENCY REPORT NUMBER

11.

SUPPLEMENTARY NOTES

The views expressed in this thesis are those of the authors and do not
of the Department of Defense or the United States Government.
12a.

DISTRIBUTION AVAILABILITY STATEMENT

12b.

Approved

13.

reflect the official policy or position

for public release; distribution

ABSTRACT (Maximum

is

DISTRIBUTION CODE

unlimited.

200 words)

The term steganography is descriptive of techniques used to covertly communicate by embedding


a secret message within an overt message. Such techniques can be used to hide data within digital images
with little or no visible change in the perceived appearance of the image and can be exploited to covertly
export sensitive information. This thesis explores the data capacity of bitmapped image files and the feasibility of devising a coding technique which can protect embedded data from the deleterious effects of
lossy compression.
In
bits

its

simplest form, steganography

in

images

is

accomplished by replacing the

least significant

of the pixel bytes with the data to be embedded. Since images are frequently compressed for storage

or transmission,

it

is

desirable that a steganographic technique include

to counter the errors caused

by lossy compression algorithms.

some form of redundancy coding

Specifically, the Joint Photographic Expert

Group (JPEG) compression algorithm, while producing only a small amount of visual distortion, introduces a relatively large number of errors in the bitmap data. These errors will effectively garble any noncoded steganographically embedded data, (continued on reverse)
14.

SUBJECT TERMS

15.

NUMBER OF PAGES

16.

PRICE CODE

20.

LIMITATION OF ABSTRACT

Steganography, Covert Channels, Security, Compression

17.

SECURITY CLASSIFICATION

OF REPORT
"Unclassified

NSN 7540-01-280-5500

18.

SECURITY CLASSIFICATION

OF THIS PAGE
Unclassified

19.

SECURITY CLASSIFICATION

OF ABSTRACT

Unclassified

UL
Standard Form 298 (Rev 2-89)
Prescribed bv ANSI Sid 239-18

Block

13 continued:

This thesis shows

that,

although there are numerous protocols for embedding data within pixels,

is always the number of bits modified in each pixel. A balance must be found between
amount of data embedded and the amount of acceptable distortion. This thesis also demonstrates that,
despite errors caused by compression, information can be encoded into pixel data so that it is recoverable

the limiting factor


the

after

JPEG processing, though

Standard

Form

298, (Reverse)

not with perfect accuracy.

Approved

for public release; distribution

is

unlimited

IMPLEMENTATION AND EFFICIENCY OF STEGANOGRAPHIC TECHNIQUES IN BITMAPPED IMAGES AND EMBEDDED DATA SURVIVABILITY
AGAINST LOSSY COMPRESSION SCHEMES
Daniel L. Currie HI
Lieutenant, United States
B.S.,

West Virginia

Navy

Institute of Technology, 1987

and
Hannelore Campbell
Lieutenant, United States
B.S.,

Navy

Vanderbilt University, 1991

Submitted

in partial fulfillment

of the

requirements for the degree of

MASTER OF SCIENCE IN COMPUTER SCIENCE


from the

NAVAL POSTGRADUATE SCHOOL


March 1996

'

KNOX LIBRARY
3TGRADU
!EY CA 91

ABSTRACT
The term steganography

is

descriptive of techniques used to covertly

communicate

by embedding a secret message within an overt message. Such techniques can be used
hide data within digital images with

little

or

no

change

visible

in the

to

perceived appearance

of the image and can be exploited to covertly export sensitive information This thesis
explores the data capacity of bitmapped image files and the feasibility of devising a coding technique which can protect

embedded data from

the deleterious effects of lossy

com-

pression.
In its simplest form, steganography in
least significant bits

images

is

accomplished by replacing the

of the pixel bytes with the data to be embedded. Since images are

quently compressed for storage or transmission,

it is

fre-

desirable that a steganographic tech-

nique include some form of redundancy coding to counter the errors caused by lossy

compression algorithms. Specifically, the Joint Photographic Expert Group (JPEG) compression algorithm, while producing only a small
relatively large

number of

errors in the bitmap data.

any non-coded steganographically embedded


This thesis shows

amount of visual

that,

These errors

distortion, introduces a
will effectively garble

data.

although there are numerous protocols for embedding data

within pixels, the limiting factor

is

always the number of

bits

modified

in

each pixel.

balance must be found between the amount of data embedded and the amount of acceptable distortion. This thesis also demonstrates that, despite errors caused by compression,

information can be encoded into pixel data so that

though not with perfect accuracy.

it is

recoverable after

JPEG

processing,

ool

VI

TABLE OF CONTENTS
I.

INTRODUCTION
WHAT IS STEGANOGRAPHY?
B
PUBLISHED WORK ON STEGANOGRAPHY
C
USES OF STEGANOGRAPHY

A.

1.

1
1

Subliminal Communication

2.

Integrity

3.

Illicit

and Authentication

Exfiltration

n.

SCOPE OF THESIS
STEGANOGRAPHIC TECHNIQUES
A
WRAPPER FILES
B
IMAGE STORAGE
PROTOCOL EVENT SELECTION
C.
D.
MESSAGE LOCATION
E
COMPARISON-BASED BIT INSERTION PROTOCOLS

VI

10
[10]

Bit Inversion

12
13

3.

Bit Deletion

14

4.

Flag Bit

15

5.

Threshold Bits

15

MESSAGE BIT INDEPENDENT INSERTION PROTOCOLS


Direct Bit Replacement
Neighbor Parity

16
17
17

STEGANOGRAPHIC DATA CAPACITY


DATA EMBEDDING DENSITY
B
THEORETICAL LIMITS
PERCEPTUAL LIMITS
C
1.

Pixel Structure

2.

Content and Texture of Images


Hidden Data Location Within an Image

3.

10

Bit Insertion

A.

EMBEDDED MESSAGE SURVIVABILITY


A
IMAGE PROCESSING ISSUES
B
JPEG COMPRESSION
JPEG EFFECTS ON IMAGE DATA
C
D

2.

1.

IV

1.

2.

HI

19
19
19
19

20
20
23

25
25

25

1.

Effects on Pixels

26
27

2.

Error Distribution

28

ERROR CORRECTING SCHEMES

E
AN EFFECTIVE CODING SCHEME
DISCUSSION AND CONCLUSIONS
STEGANOGRAPHY FOR ILLICIT EXFILTRATION
A
STEGANOGRAPHIC APPLICATIONS
B

SUGGESTIONS FOR FURTHER RESEARCH


vii

29
31

33
33

34
35

AN UNEXPLORED DISCIPLINE

35

1.

Detecting Steganography in Image Files

35

2.

How Widespread

36

4.

Use of Steganography?
Steganography on the World Wide Web
Steganography in Printed Media

5.

Anti -Steganography Measures

36
37
39

3.

is

the

REFERENCES
APPENDIX: SOURCE CODE
A
GENERIC STEGO EMBEDDING PROGRAM
B
GENERIC STEGO EXTRACTION PROGRAM
IMAGE FILE COMPARISON PROGRAM
C
D
RGB VECTOR ENCODING STEGO PROGRAM
RGB VECTOR STEGO EXTRACTION PROGRAM
E
F.
STEGO FUNCTIONS HEADER FILE

LIST OF

INITIAL DISTRIBUTION LIST

36
36

39
45
56
61

68
72
77

Vlll

I.

A.

INTRODUCTION

WHAT IS STEGANOGRAPHY?
Steganography

communication

is

is

closely

related

overt, but the content

to
is

cryptography.

secret,

where

Unlike cryptography

steganography

is

the science of secretly

communicating by means of concealing information within some data medium


encompasses a large variety of techniques and protocols. Steganography can range from

It

simple modification of English text by modulating active and passive voices to utilizing the
least significant bits in digital

image pixels

Any steganographic technique will

to unobtrusively

necessarily cause

original data.

The key

hidden data

undetectable visually by either a

or one

who

is

does

some

distortion or modification of the

human observer who knows the

data

by the
there

is

not.
in

1499 by Johannes Trimethius (1462-1516)

used apparently meaningful prayers to hide covert messages


along with cryptography for centuries

made

additional information

to successful steganography is to ensure the distortion caused

The term steganography was coined

has been

embed

in secret

[7].

communications,

Although

in the

has been used

until recently, little effort

to formally study or define steganography. Interest has

however, as evidenced by an increase

it

who

been building,

amount of discussion of steganography

in the

cryptographic and computer security communities.

B.

PUBLISHED

WORK ON STEGANOGRAPHY

search of the literature on and relating to steganography yields very few works

exclusively discussing the subject. Steganography

offshoot of cryptography.

It

is

usually addressed as an adjunct or

has rarely been discussed as a science in

its

own

right This is

probably because, until the advent of high volume/high speed data communications, the
threat of covert

communication was

relatively small given the usually small

provided by most steganographic techniques

bandwidth

One of the

known published

earliest

"Steganographia"

by

where

His best known invention

words was used

Trithemius

Trithemius.

substitutions and systems

is

treatises

certain letters in

the

"Ave Maria"

to

surrounding

200 years

it

it

caused

it

it

be banned

to

be an ordinary prayer
its

that

when

[7],

perceived connection with magic and

1609 by the

was banned, "Steganographia" was

text.

which each of many carefully selected

was not published

in

volume

vowel-consonant

simple

The words were chosen such

"Steganographia" was controversial due to


the occult. Although written in 1499,

described

six

nonsense words comprise the hidden

in

to represent a plaintext letter.

combined they made sense and appeared

on steganography was the

until

Roman

1606 and the controversy

Catholic Church. During the

was the

reprinted several times and

subject

of extensive written debate by scholars.

Not

until the twentieth

century did steganography

become recognized

as a significant

threat to information security. In [7]

Kahn

intelligence within legitimate civilian

communications during wartime. During World

discusses the threat of covert transmission of

n, concern over such communications led to censorship of pictures,

crossword puzzles, newspaper clippings,

More

recently, there has been a

classified military data.

When

channels being used to

move

and

data

is

chess boards,

etc.

huge increase

declassified or

in large scale electronic storage

downgraded, there

data from one classification

domain

is

of

a threat of covert

to another. In [9]

McHugh showed that it is a simple matter to hide information within digital

then later extract

War

Kurak

images and

it.

Utilizing a subliminal channel for transmission of authentication data

The Prisoners' Problem

and

subliminal channel communication by

of covertly transmitted data

is

Channel

the Subliminal

Simmons

[12].

is

the subject of

Although referred to as

rather than steganography, authentication

an important aspect of steganography. If a third party

discovers the steganograph being used, there

is

a risk of spoofing.

C.

USES OF STEGANOGRAPHY
Steganography
policy,

security

employment:
exfiltration

often thought of only as a tool for a malicious user to subvert a

but there are actually three fundamental

subliminal

of data.

malicious or

is

integrity

and

and

authentication,

illicit

It is

important to note that subliminal communication

We

define subliminal communication as simply a transfer of data in a

illicit.

manner which conceals the


is

communication,

of steganography

classes

being transmitted.

fact that data other than the overtly

Dlicit exfiltration,

on the other hand,

is

is

not necessarily

communicated information
a deliberate violation of a

security policy.

Subliminal Communication

1.

Secretly transferring data

is

accomplished by using a technique to hide the data within

another set of data called a wrapper. This wrapper


stream.

covert channel

is

one

in

normally used for communication


channel in that

channels

is

it is

may be

virtually

any type of file or data

which communication takes place by means

[5],

steganographic channel

is distinct

that are not

from a covert

concomitant with overt communications. The variety of steganographic

limited only by the creativity of the communicator.

Some methods

of

concealing data include:

Modulating word or

line spacing in a text

Using the

of each word or paragraph as a

first letter

document
letter

of the message

Modulating the tense or voice of verbs

Using the

least significant bit(s)

Using the LSB(s)


2.

Integrity

Integrity

in a digitized

(LSB) of each

sound

image

file

file

and Authentication

of data

is

another

important

aspect

Steganographic techniques can be used to embed a


that the data cannot

pixel in an

be modified by even a single

of computer

seal within

bit

an image

system
file in

security

such a

way

without detection. This provides both

authentication and tamper-proofing of the image. Steganography has the advantage that the

presence of embedded data

is

usually not detectable and cannot be altered or

removed

without knowledge of the exact technique used.


In [14],

Walton describes a technique which guarantees the

integrity

of image

files.

This method employs an algorithm which visits certain, randomly chosen pixels, modifying

them

to

visited.
tell if

produce a desired checksum value. The

seal

key

is

the order in which the pixels are

This "random walk" sealing method ensures integrity since "...an interloper cannot

way of finding

an image has been sealed, has no

blanket your image with

LSBs, and cannot

the unchanged

possible seals."

all

Documents and images

are tagged for a variety of reasons from enforcing copyright

ownership to archival marking of data. Steganographic techniques provide an unobtrusive

way

to tag a file without lengthening the file or subjecting the tag to possible alteration or

removal.

AT&T

postscript files

explored a tagging system

were used

to

encode a

serial

in

which subtle changes

rely

[2]

steganographic technique for authentication and integrity will necessarily

on protecting the steganographic method and any keys used to encrypt the hidden

Additionally, once data has been steganographically

taken to keep the original

two

spacing in

number. This technique proved to be effective

even when the document was photocopied numerous times.

A successful

in line

files

3.

file

separate from the altered

file.

file,

care must be

Allowing comparison of the

undermines the secrecy of the steganographic channel's existence.

Dlicit Exfiltration

Of the many means


insidious in that

it

of

illicit

exfiltration

data files are being

embed

of data, steganography

is

perhaps the most

requires a sophisticated user to implement and can provide a high

bandwidth communication channel.

user can

embedded within

data.

It is

downgraded from

an especially grave threat

an environment where

a high security class to a lower one.

classified data within a

expects to be downgraded.

in

wrapper

file

The malicious

of equal classification which he

The data can then be extracted when the wrapper

to a lower security classification

domain

file is

moved

D.

SCOPE OF THESIS
This thesis

is

intended to be expository on the subject of steganography, to survey

steganographic techniques and their efficiency, and to investigate the feasibility of devising
a robust form of steganography that can survive lossy compression.

highlight

the

threat

of steganography

to

system

security

Our

and

ultimate goal

to

is

demonstrate

to

steganographic technique which could be used to thwart a multi-level system security


policy in an
subject.

image

storage, processing,

and downgrading system which

relies

on a trusted

STEGANOGRAPHIC TECHNIQUES

II.

WRAPPER FILES

A.

wrapper

is

the

medium

into

which a message (hidden data)

is

embedded. As with

encryption, steganography can be performed on a block of data or on a data stream. For the

purposes of this thecis


files rather

we

will

be concerned with block steganography carried out on data

than stream steganography.

variety of data files are

commonly used

in

computer systems. Each type of file has characteristics which must be taken into account

when devising

a steganographic technique. In general, files in

which the data

stored with

is

a far greater accuracy than necessary for the data's use and display are suitable for

steganography. Image, Postscript, and audio

files are

among

those which

fall

into this

category, while text, database, and executable files do not.

A text file contains a relatively low data density.


which comprise the characters, are off

bits

cause obvious damage to the

file.

Certain aspects of the

limits to steganography

file,

such as the

because any changes

Other aspects, such as character, word, or line spacing,

can be subtly modified to hide data. These techniques yield a low bandwidth, but are useful
for

document tagging or any other purpose which requires


With the increased use of multimedia

common and
human
be

provide an ideal

medium

amount of hidden data

a small

in applications,

for steganography.

sound

Due

files are

to the imprecise nature of

hearing, modifications to a sound file by a steganographic technique

relatively large to

much more

would have

to

be detected by a human observer. With a properly designed

steganographic technique, even an informed observer listening to the modified and

unmodified sound

files in

Consequently, a sound

file

quick succession would have difficulty hearing a change

can hold a

much

larger

message than can be embedded

in a text

file.

By

far the

most readily available and

are ubiquitous in a large

number of

suitable

applications.

high data density and small changes can be

wrapper

files are

As with sound

made without

image

files,

detection

files.

image

Image
files

files

have a

B.

IMAGE STORAGE
The format

in

which images are created and stored varies with the

image can be as simple as a


corresponding to

bit

value of

bi-level

or

0.

format where each pixel

is

application.
either

The

on or off

A better quality image can be made by using 8 bits for

each pixel, allowing 256 shades of gray per pixel. Using 24 bits for a pixel to encode a color
value yields an even more accurate and realistic image. Clearly any
pixel

number of bits and

encoding schemes can be used to provide any desired level of detail. In general, as the

number of

bits

used to represent a discrete component of a

increases, the file's utility as a

Due

file (in this

case a pixel)

wrapper increases.

to their gross granularity, bi-level

images are

difficult to utilize as

wrapper

files.

A steganographic technique would introduce noise into the image which would likely cause
noticeable degradation. This effect

is

mitigated in complex or noisy images. In sparsely

detailed images, however, any changes will probably be easily spotted.

Grey scale images are much more suitable for hiding messages. Altering the low order
bit

of the eight bits used to represent a pixel causes only a 1/256, or 0.39%, change in the

shade of grey. This small change


the four

low order

bits

induces

at

is

undetectable by the

differs

into the

wrapper

from the message

file,

bit.

eye. Furthermore, altering

most a 16/256, or 6.25%, change.

The percentages above represent a worst case

embedded

human

scenario.

When

message

bit is

the target bit in the wrapper file will be changed only if

The likelihood

that the target bit will

be changed

it

is 0.5.

embedding n

Therefore,

wrapper

bits will result in

an average of n/2 bits being modified in the

file.

Original

Oil

1|0

Oil

Wrapper
Pixels

Pixel

Message

Pixel 2

Pixel 3

|i|o|l|l|l

Bits

Transmitted

Steganographed
Pixels

Pixel

Figure

Figure

of 8

1:

demonstrates

bit pixels

Direct Insertion of Message Bits

how

message can be embedded

representing 256 shades of grey.

bits. In

changed, resulting in a 4/256, or 1.56%, change in


in the

into a

wrapper

file

composed

The steganographic technique replaces

four low order bits of each pixel with the data

embedded

Pixel 3

Pixel 2

its

the

first

pixel only

two

the

bits are

shade of grey. The message

bits

therefore no change

was

second pixel matched the pixel's original

bits,

made.
Color images, specifically 24

bit color

images, are extremely

extrapolate from the above example and see that a 24 bit pixel

more embedded data with only


will focus

on

this type

is

common. One can

easily

capable of holding

much

a small change in the appearance of the pixel. This thesis

of file. The amount of data which can be embedded

in a

24

bit color

image

and the degree of the resulting distortion of the image as a whole

file

will

be

investigated.

PROTOCOL EVENT SELECTION

C.

When

applying a steganographic technique to a wrapper

for the selection of the specific points in the file at


insinuated. This

the

PES

is

known

purposes,

height.

must be a protocol

which the message

bits will

as protocol event selection (PES). In the context of

image

be

files

it

involves selecting pixels in an image

numbered from
can

It

an integral part of any steganographic technique. For our

is

be

to

W*H, where

defined

as

file

every pixel p where p


suitable as long as

it

mod

is

mathematical

selects

Another PES method

equal to

linear

function

to

arrangement of

image and

simple example would be to use

every even numbered pixel).

embed

the desired

[14].

may be designed

The walk, however

it is

H is the

which generates numbers

Any

function

number of bits.

based on a predetermined key which provides a

is

order in which pixels are used. This key

"walk" from pixel to pixel

(i.e.

enough pixels

viewed as a

the width in pixels of the

is

corresponding to the numbers of the pixels to be used.

is

there

algorithm will select pixels in which data will be hidden.

The PES algorithm

pixels

file

map

of the

so as to produce a pseudo-random
generated, must not visit the

same

pixel twice.

When

incorporating a predetermined key scheme into a steganographic protocol,

provision must be

made

for

embedding the key

passing the key separately. This

PES method

is

in the

image along with the hidden data or

also very sensitive to errors in the key since

any key error would make complete recovery of the embedded data nearly impossible.

D.

MESSAGE LOCATION
Once

will

PES method

is

established, the location within the

image where the message

be hidden must be determined. Commonly, the entire image

maximize the amount of data which can be hidden. Using the


message over the image so as

to reduce the density

10

entire

is

used

in order to

image also spreads the

of the hidden data and thereby reduces

the perceived distortion of the image. Nevertheless, there are several techniques and

reasons for localizing the message within an image

The goal of steganography

human

eye.

One way of doing

is to

hide data in such a

this is to put the

way

hidden data

to

be noticed. Most pictures have a subject which

is

naturally drawn.

is

that
in

not detectable by the

it is

an area where

the center of attention to

Lacking a particular subject or area of interest, the eye

the center of the picture. Clearly, these areas should be avoided

technique. Another consideration for the location of hidden data

is

it

is

unlikely

which the eye

will

be drawn to

by a steganographic
the texture, or "busy-

ness," of different areas of the picture. For example, in a photograph of a forest with clear

blue sky overhead, distortion would be more easily detected in the sky area than in the
forest area.

Setting aside the issue of covertness,

it is

often desirable to provide redundancy in the

hidden data to counter the effects of errors introduced into the image

file.

Figure 2 shows

possible arrangements of redundant hidden data.

Figure

2:

(Shaded areas indicate hidden data)

Incorporating redundancy

in

this

way

provides some protection

introduced in transmission, processing, and compression.


the hidden data

E.

the entire

image

file is

actual insinuation of

message

bits

errors

can also allow for recovery of

not available.

COMPARISON-BASED BIT INSERTION PROTOCOLS


The

PES

when

It

against

[10]

can be accomplished by several protocols The

technique can be viewed as a means of moving a pointer to an insertion point within

11

the bits of the wrapper


to place a

message

bit in the

of the insertion point


bits

Having selected an

file.

insertion point, an insertion protocol is used

wrapper file. The insertion protocol can involve a replacement

bit or its

neighbors, or insertion of the message bit between wrapper

near the insertion point. Inserting message bits between wrapper bits has the effect of

shifting

all

the wrapper bits after the insertion point. This will cause undesirable effects in

some types of wrapper


to the pixels

(i.e.

the

files.

image

Specifically, if bits in an

image

file are shifted

without regard

treated as a continuous stream of bits rather than a series

file is

of discrete pixels) then insertion of a few bits will essentially randomize the image.

Bit Inversion

1.

The
bit is

insertion point bit

then the insertion point bit must be a

Likewise,

if the

message

encode the message

specially selected to

is

bit is

and

bit. If

inverted to represent the message

is

then the insertion point bit must be a

1.

Message
1

Bits

Original
1

Insertion

Insertion

Insertion

Point

Point

Point

10;

1;

N
1

10

Wrapper
Pixels

Pixel

Pixel 2

Pixel 3

Transmitted

Steganographed
Pixels

l|l

Pixel

Figure

3:

Pixel 2

Bit Inversion

12

the message

Pixel 3

bit.

This technique requires that the original wrapper be compared to the stegotext to
recover the message.

When comparing

the

files,

every differing

and

bit

its

value

is

noted

Bit Insertion

2.

The
message

insertion point bit


bit is

is

chosen to be the opposite value of the message

then inserted immediately prior to the insertion point

bit

The

bit.

Message
Bits
Insertion

Insertion

Insertion

Point

Point

Point

4
Original

10

liO

lffljl

Wrapper
Pixel

Pixels

Transmitted
Steganographed
Pixels

Pixel

Figure

The message
where

a bit differs

when

the

is

Pixel 2

10

Pixel 3

11

110

Pixel 3

Pixel 2

Bit Insertion

extracted by comparing the wrapper with the stegotext and noting

and

message

4:

its

value. In this technique an extra bit

bit is extracted, the bits to the right

alignment.

13

is

inserted in the

must be

wrapper so

shifted left to regain

3.

Bit Deletion

chosen as a pair of bits; either a 01 or 10 depending

In this case, the insertion point is

on the message

bit.

If a

deleted. Similarly if a

be inserted then a 10 pair

is

to

is

to

be inserted, a 01 pair

is

is

chosen and the

chosen and the

of the pair

of the pair

is

is

deleted.

Message
Bits

Original
1

Insertion

Insertion

Insertion

Point

Point

Point

ijo[i!

Wrapper
Pixels

Transmitted
Steganographed
Pixels

Pixel

Pixel

Figure

Again, the message


stegotext.

is

5:

Pixel 2

100

11
1

100 jmoil
Pixel 3

iolo

Pixel 2

00

1:1

Pixel 3

Bit Deletion

extracted by noting the difference between the wrapper and the

A right shift is necessary to regain

alignment and continue with the comparison.

14

4.

Flag Bit

With

this technique, a

wrapper

preceding the selected wrapper

equal to the message bit

bit

bit is inverted

selected.

is

and acts as a flag for the message

The

bit

bit.

Message
1

Bits

Original

110

Wrapper
Pixels

Pixel

Pixel 2

Pixel 3

Flag

Flag

Flag

Bit

Bit

Bit

4/

Transmitted
Steganographed

after

is

Pixel 3

Flat Bit

failure.

Threshold Bits

Like the flag

however a

6:

Pixel 2

no

extracted by comparing the wrapper to the stegotext and noting the bit

each comparison

5.

0:0

Pixel

Figure

The message

A/

111

Pixels

bit protocol,

certain

an inverted

odd number n of

encode the value of the message

bit.

bits,

bit acts as a flag for the

message

immediately following the flag

If the

number of

15

l's in the

n bits

is

bit.

In this case

bit are

used to

greater than the

number of O's then


message

bit is 0.

the

message

bit is

Similarly, if there are

1.

more

O's than l's then the

This protocol allows for error correction.

Message
1

Bits

Original
1

Insertion

Insertion

Insertion

Point

Point

Point

10

100

Wrapper
Pixels

Pixel

Transmitted
Steganographed

wrapper

file

Flag

Bit

Bit

10

100

Pixel 2

0|1

Pixel 3

Flag

10

11101

Pixel 3

3)

7:

Threshold Bits

in the previous section require the receiver to

and the stegotext

bit(s) are selected

based on the value of the message

entirely different

mentioned

file.

embed

image

is

is

to

bit.

is

have both the original

because the insertion point

Therefore the only

compare the wrapper with the

way

for the

stegotext. This

from the key- or algorithm-based protocol event selection techniques

earlier.

Frequently,

wrapper

message. This

to extract the

receiver to identify the insertion points

to

Oil

MESSAGE BIT INDEPENDENT INSERTION PROTOCOLS


The protocols

is

10

Bit

Figure

F.

Pixel 2

Pixel

100

Flag

Pixels
(note: n

0J1

it

is

inconvenient or impossible for the receiver to have the original

For example,

in

classified data in an

an image downgrading scenario,

image which he expects

downgraded, the original wrapper

comparison

in

file is

to be

possible for a misfeasor

downgraded. Once the wrapper

no longer available

an extraction algorithm For this reason,

16

it is

when designing

to

be used for

a steganographic

application
original

1.

it is

preferable to use a protocol which does not rely on the availability of the

wrapper

file.

The following

examples of this type of protocol.

are

Direct Bit Replacement

In this protocol, the insertion point bit

protocol

2.

was demonstrated

Figure

in

simply replaced by the message

is

bit

This

1.

Neighbor Parity

As with

the threshold bit protocol

discussed

neighboring bits and modifies the insertion point

bit to

protocol

this

earlier,

examines n

achieve a desired parity.

Message
01

Bits
Insertion

Insertion

Insertion

Point

Point

Point

Original
1

10 0l|l

oil

Wrapper
Pixels

Pixel

Pixel 2

Transmitted
Steganographed

this

requires the

8:

Pixel 2

example, odd parity represents

PES

1 1

Pixel 3

Neighbor Parity

and even parity

to maintain at least n bit spacing

effect of this technique is to essentially

Sometimes a message bit of 1


as a

3)

Figure

For

Pixel

A/

>V
....

Pixels
(note: n

Pixel 3

will

0.

Clearly, this technique

between insertion points The overall

randomize the way message

be represented

1.

17

bits are represented

at the insertion point as a

and sometimes

18

STEGANOGRAPHIC DATA CAPACITY

III.

DATA EMBEDDING DENSITY

A.

The

relationship between the size of an

be hidden

in

it is

number of data

image

file

very straightforward. The steganographic data density, defined as the

bits per

image

byte, directly determines the total

be hidden. The general formula for the data capacity


data capacity

where

(W

in

bytes

bytes per pixel) *

W and H are the image width and height

embedded per

and the amount of data which can

in pixels

is:

D)

and

amount of data which can

8 bits per byte,


is

the

number of data

bits

pixel.

THEORETICAL LIMITS

B.

As described above,

the

number of bytes of data which can be hidden

on the size of the image

file

and the density

turn,

at

which data

is

is

dependent only

embedded. The density

determined by the acceptable degree of distortion as will be described

is,

in

in the next

section.

The amount of information which can be


compression.

From

the point of

stored can be

view of the steganographic algorithm the data

is

a stream

no reason why a stream of bytes representing ASCII characters cannot be

of bytes There

is

embedded

compressed form thereby increasing the

in a

improved through the use of

total

amount of information which

can be stored in a given image.

C.

PERCEPTUAL LIMITS
In deciding

on a hidden data density one must

image degradation and the desire

to

strike a

balance between the amount of

maximize the amount of data which can be stored

image. Increasing the data density increases the amount of degradation. The trick
the data density threshold at

fuzzy. Three factors

which an uninformed observer may notice

which influence

that the

this are the pixel structure, the content

the image, and the hidden data location within the image.

19

is

in

an

to find

image

is

and texture of

Pixel Structure

1.

In

color

any image

256

format which uses less than 24

map must be made

common

order for the

in

file to

pixel structure of this kind

map

colors, a color

is

necessary to

is

bits

per pixel,

some provision

be displayed on a color monitor. This

of converting the pixel value to a 24

to the necessity

most

file

bit

for a

is

due

value for the display driver. The

8 bits. Since an 8 bit value can only represent

map

the

256 colors

to the 16,777,216 possible

colors.

Any

attempt to

embed

data in an 8 bit pixel value will result in that pixel value pointing

to an entirely different color value in the color

the result of
pixel value

24

some kind of quantization of the

bit

image

very large and

the color. This

is

file

format

it is

map

the pixel value

is ideal

due to two

for steganographic purposes.

factors. First, although the

file is

of the pixel

24

making

[3],

bit pixel is

The number of possible

colors

a noticeable change in

human eye can

conditions, viewing an altered

bits,

an 8 bit image

in the color

distinguish a large

image on a monitor without the

image makes detecting small color changes

may be 24

in

colors present in the image, so changing a

possible to change several bits without

benefit of a reference

bits

color

8 bit color channels: red, green, and blue.

number of colors under ideal

24

by even a small amount may cause a drastic change

composed of three
is

map.

unlikely. Second, while

most personal computers and workstations do not display

of color on the monitor. The 24

bit pixels are usually

mapped

internally to 4, 8, or

16 bits for the display. Further, every monitor will have small differences in color
saturation, brightness, contrast, etc.

2.

The

Content and Texture of Images


characteristics of the

image

itself is

another factor which must be considered

when

applying a steganographic technique. The overall variety of colors, shapes, and textures and
their relative sizes

and dispositions can affect the detectability of embedded

example,

9,

in

Figure

the seagull

is

seen against a sky which

is

data.

composed of only

For

few

shades of blue. Color distortion introduced in this mostly blue field will appear as specks

20

of darker or lighter blue, or even a different color, which contrasts with the blue around
as seen in Figure 10. (Distortion has been enhanced for illustration

Figure

9: Seagull,

730x480, 24

it

bit pixels [8]

Figure 10: Seagull with 136,608 bytes of data embedded

A good choice for an image to be


i.e.

contains

many

used as a wrapper would be one which

different shapes, colors

and textures

21

is

very busy,

In this type of picture, the

steganographic distortion will be lost in the profusion of

Figure
but

1 1

it is

and Figure

much

12.

Figures

less visible in

[ 1

0]

and

[ 1

2] contain the

detail.

This

is

demonstrated

same amount of embedded

Figure 12.

Figure 11: Glasses, 730x480, 24

bit pixels [8]

in

..'
'

:'.

'

Figure 12: Glasses with 136,608 bytes of data embedded

22

in

data,

Hidden Data Location Within an [mage

3.

The steganographic data capacity of an image


In the case

where

less than the

maximum amount

to avoid creating a line of demarcation

is

a function of the embedding density

of data

is

embedded, care must be taken

between the area containing hidden data and the

portion of the image which has not be tampered with. In Figure 10 the hidden data

is

obviously located in the bottom portion of the image.

A solution to this

problem

is to

compute

n,

the

number of bytes

by the number of image bytes necessary to hold the embedded

data.

in the

Then,

image divided

in the

embedding

algorithm, use every nth image byte. This will spread the hidden data over the entire image,

reducing

its

detectability.

Spreading out the data in Figure 10 results in Figure

a significant improvement.

Figure 13: Seagull with embedded data spread out

23

13; clearly,

24

EMBEDDED MESSAGE SURVIVABILITY

IV.

A.

IMAGE PROCESSING ISSUES


Both newly created and existing images often undergo modification as a

result

of some

form of processing Images can be compressed using lossy compression techniques, can be
digitally

enhanced, or they can have other images or graphics overlaid on them. All forms

of 'invasive' processing are a threat to any steganographically embedded message


Alteration of any of the pixels containing

message

survivability,

message

some form of error

bits

correction

can garble the message.

is

necessary.

The most frequently encountered source of image degradation


the next

two sections we

will

examine the

Group (JPEG) compression standard and

loss caused

To enhance

is

lossy compression In

by the Joint Photographic Experts

the error correction required to

compensate for

it

[6]

B.

JPEG COMPRESSION
The JPEG compression standard has been developed

compression

tools.

JPEG

has four

modes of operation designed

continuous-tone image applications

coder/decoder which

JPEG works

is

to provide efficient, flexible

Most

very effective and

applications utilize the Baseline sequential

is

in several steps. First the

to support a variety of

sufficient for

many

applications. [13]

image pixels are transformed

into a luminance/

downsampled

chrominance color space [11] and then the chrominance component

is

reduce the volume of data. This downsampling

human eye

more

sensitive to

luminance changes than

is

it is

possible because the

to

is

to

much

chrominance changes. Next, the pixel

values are grouped into 8x8 blocks which are transformed using the discrete cosine

transform (DCT).

The

DCT

yields an 8x8 frequency

map which

contains coefficients

representing the average value in the block and successively higher-frequency changes
within the block. Each block then has

its

values divided by a quantization coefficient and

the result rounded to an integer. During this quantization

25

is

where most of the

loss caused

by

JPEG

occurs.

Many

of the coefficients representing higher frequencies are reduced to

zero. This is acceptable since the higher frequency data that is lost will

change

visually detectable

Huffman coding
in

C.

in the

JPEG applications is to add

little

image. The reduced coefficients are then encoded using

to further reduce the size of the data. This step is lossless.

The

final step

header data giving parameters to be used by the decoder [13]

JPEG EFFECTS ON IMAGE DATA


As mentioned

before,

embedding data

simple steganographic technique, but


investigate the possibility of

embedded data

it is

image and where


At
to

produce very

first

it

in the least significant bits

employing some kind of encoding

image

predict mathematically

impractical since the

DCT

To

to ensure survivability of

JPEG

causes in an

occurs.

it

glance, the solution

is

cannot survive the deleterious effects of JPEG

necessary to identify what kind of loss/corruption

in the

of image pixels

may seem

be to look

to

where changes

at

the compression algorithm to try

the original

to

pixels will

occur.

This

is

converts the pixel values to coefficient values representing 64

basis signal amplitudes. This has the effect of spatially "smearing" the pixel bits so that the

location of any particular bit

is

complex relationship between the

spread over

all

the coefficient values

original pixel values

Because of the

and the output of the DCT,

it

is

not

feasible to trace the bits through the compression algorithm and predict their location in the

compressed

Due

data.

to the

complexity of the

effects is called for.

To

JPEG

algorithm an empirical approach to studying

study the effects of JPEG, 24 bit

compressed, decompressed, and the resulting

The

BMP

file

format was chosen for

file

its

Windows

saved under a

its

BMP format files were

new

filename.

simplicity and widespread acceptance for

image processing applications. For the experiments, two photographs, one of a seagull and
one of a pair of glasses (Figure 9 and Figure
detail

and number of colors

effects,

JPEG

is

1),

were chosen

for their differing

sensitive to these factors.

To

investigate

an analysis was conducted to locate and quantify the errors introduced

26

amount of
JPEG's

Effects on Pixels

1.

Table
files

we
bits

below shows the

and the

JPEG

results

of a byte by byte comparison of the original image

processed versions, normalized to 100,000 bytes for each image. Here

see that the seagull picture has fewer than half as

(MSB)

equivalent

as the glasses picture.

While the

many

most

significant

(LSB) have an

essentially

errors in the

least significant bits

number of errors.

MSB

LSB

Glasses

744

4032

10247

21273

33644

42327

27196

48554

Seagull

257

99)

2821

7514

15039

29941

41593

46640

Table
Table

shows

corresponding pixels

the

Errors introduced by

Hamming

in the original

and

distance

JPEG

per bit position

(number of differing

JPEG processed

files

bits)

between

normalized to 100,000 pixels

for each image. Again, the seagull picture has fewer errors.

1-3

4-6

7-9

10-12

13-15

16-18

19-21

Glasses

15581

37135

30337

11976

2205

172

Seagull

24188

38710

17564

4631

409

43

Table

Given the information


lower

5 bits

and recover
garbled by

in

2:

Hamming

Table

1, it is

distances between pixels

apparent that data embedded in any or

would be corrupted beyond recognition. Attempts


it

after

JPEG

22-24

to

embed

all

of the

data in these bits

processing showed that the recovered data was completely

JPEG

27

Error Distribution

2.

Although

JPEG causes

number of bit

pixels suffering the largest


in the pixel values.

(Figure 9) and the

which has a

errors throughout the image, the

Figure 14

JPEG

Hamming

is

most severe

processed version of the same

file.

Each black dot indicates a

: -:'

'%

->

'-

f-?^i-

/''<-

-C

Map

of errors of

Given the nature of the

JPEG

applying an error correction scheme

this will

pixel

distance of more than 8 from the corresponding original pixel.

m.

severely affected by

the

a pixel by pixel comparison of the original seagull picture

v-v'

Figure 14:

is,

inversions, are located along edges or transients

%?-

errors, that

JPEG

more than

-Jt'

8 bits per pixel

problem of embedding the data and of

errors, the
is

,<.

challenging.

The

indicates that data should be

fact that the

embedded

in

lower order

higher order

bits are
bits,

but

cause more degradation of the image and compromise the effectiveness of the

steganographic scheme. Also, since the number of errors


bit positions, a

corruption.

The

robust error correcting scheme


price of robust error correction

the data. This reduces the total

is

is

is

high and distributed across

needed to protect the hidden data from


a large

overhead which must be added to

amount of information which can be hidden.

28

all

ERROR CORRECTING SCHEMES

D.

Since a straightforward substitution of pixel bits with data bits proved useless, a simple

coding scheme to embed one data

lower 5
1.

On

bit

of each byte by replacing the

bits

than 7 in an

The theory was

upward

that perhaps

direction and 8 in a

correct errors. This approach failed.


to byte values

unrecognizable. This
bit

tried.

A bit was

with 01000 to code a

and

would be decoded

1 1 1

JPEG would

downward

embedded

in the

1000 to code a

and 10000 to

as a

more

not change a byte value by

direction or, if

it

did,

it

would make

changes only occasionally and some kind of redundancy coding could be used to

drastic

makes

bits

decoding, any value from 00000 to 01

11111 as a

was

per pixel byte

many

over

JPEG

is

indiscriminate about the

and produced enough errors


is

not surprising since the

coefficient values,

that the hidden data,

JPEG

some of which

amount of change

when

extracted,

it

was

algorithm spreads the value of each

are reduced to zero in the quantization

step.

The negative

results of the first

few attempts to embed data indicated

approach to encoding was necessary.


pixels

which were changed from

original.

It

was noticed

made by JPEG,

general color of the pixels. This characteristic


digital

is

to

more

subtle

processed image, the

some

in color to the

extent, maintain the

desirable in an algorithm for compressing

images; the appearance of the image should change as

to take advantage of this, a

JPEG

appearance were similar

their original

This indicates that the changes

that, in

that a

new coding scheme was

little

as possible

To

attempt

devised based on viewing the pixel as

a point in space (Figure 15) with the three color channel values as the coordinates.

The coding scheme begins by computing


(0,0,0).

Then the distance

is

found

The

is

pixel

value

corresponding to the

bit

divided by a

the distance from the pixel to the origin

number and

adjusted such that

its

the remainder

modulus

is

(r

distance

changed to

mod

n)

is

number

value being encoded. Qualitatively, this means that the length of

the vector representing the pixel's position in three-dimensional

29

RGB

color space

is

modified to encode information. Because the vector's direction


sizes

is

unmodified, the relative

of the color channel values are preserved.

Blue

(R,

G,B)

71

/
/
/
Green

\Red

Figure 15:

Suppose we choose an

in

to

20

will

arbitrary

modulus of 42. When the

bit is

be decoded as a

0.

So we want

to

move

is

31 to code a

origin

decoded, the distance

1. It

would have

was hoped

by more than 10

its

that

length modified so that the

JPEG would

in either direction thus

and any

the pixel to a middle value

one of these ranges to allow for error introduced by JPEG. In

representing the pixel


or

pixel as a point in space

be computed and any value from 21 to 41 will be decoded as a

to the origin will

value from

this case, the vector

modulus

is

10 to code a

not change the pixel's distance from the

allowing the hidden information to be

correctly decoded.

For example, given a pixel (128, 65, 210) the distance to the origin would be

computed: d

= /i28

Next we find

+ 65

dmod42

+ 2i(r = 254 38

which

is 2. If

The value of d

we are

coding a

color vector will be increased by 8 units to an ideal


13 (d = 241) units to

would be

21.

code a

1.

Note

that the

is

rounded to the nearest integer

in this pixel, the

amplitude of the

modulus of 10 (d = 262) or moved down

maximum

displacement any pixel would suffer

Simple vector arithmetic permits the modified values of the

red, green,

and

blue components to be computed. The results of using this encoding are described in the
next section.

30

Another similar technique

same way

the

computed

as

was done

is

to apply coding to the

to the distance

= 0.3R + 0.6G + 0.1B

as y

color values respectively.

value

is

only from

to

[11],

One drawback

from

luminance value of each pixel

The luminance,

origin.

where R, G, and

y,

of a pixel

in
is

are the red, green, and blue

to this technique is that the

range of luminance

255 whereas the range of the distance from origin

to 441.67.

is

AN EFFECTIVE CODING SCHEME

E.

With ordinary embedding techniques which simply replace image


one

with data

bits,

forced to use an enormous amount of redundancy to achieve a suitably low error rate

is

JPEG compression

after

bits

Also, since the lowest few bits are so badly scrambled by JPEG,

higher order bits must be used which increases the visible distortion of the image. This

is

contrary to steganography's goal of being a covert communication channel.

The distance from

the origin technique results in a lower error rate, but requires

additional redundancy to reduce the error rate to a point

recovered. Specifically, the average displacement by


[Figure 9] with respect to the origin
the

times

in a

and applying

row) yields an error

= 0.000225 per
1

triple

bit,

where p

-(1 -0.000225)
In practice,

redundancy

rate of p

is

in

embedding data

is

i.e.

the greater the

(i.e.

assumed,

is

0.8678%. Given

embed each

bit three

would yield an

error rate

per byte.

lies in the

modified to encode a

respect to surrounding pixels changes.


pixels,

be

+ 3p 2 (l-p) = (.008678) 3 + 3(0.008678) 2 (0.991322)

however, utilizing the encoding described

When a pixel

modulus of 62

the probability of a bit error. This

= 0.001799

text can

of pixels in the seagull picture

to cause an error) is 3 100 or

produce the accuracy as calculated The problem

on an image.

JPEG

2.36. Theoretically, if a

number of pixels displaced by 30 (enough

this figure

of:

is

where recognizable

number and

JPEG

is

in the

above example

nature of the effect

bit value, the

difference in

sensitive to transients

size of transients, the greater the

its

will not

JPEG

has

value with

between adjacent

number of errors

introduced by JPEG. Thus, the very act of encoding data into pixels generates an increase
in the severity

of distortion and results

in

garbling of the

31

embedded

data.

This characteristic of JPEG makes

it

a very

good anti-steganography

tool, but

does not

preclude steganographic embedding entirely. With a high repetitive redundancy factor,

some

text

may be embedded and

to the origin

extracted from a

encoding and repeating each

JPEG

bit 5 times,

recovered without error.

32

processed image. Using distance

approximately

30%

of the text can be

DISCUSSION AND CONCLUSIONS

V.

STEGANOGRAPHY FOR ILLICIT EXFILTRATION

A.

As was seen
and

is

in the

previous chapters, steganography

relatively simple to

is

capable of hiding a significant amount of information in an image

was not known

the very notion of digital steganography

The increase

in

or

file.

implement

Until recently,

was not perceived

as a threat.

communication bandwidths has encouraged a manifold increase

number of digital images being transmitted and

stored. In light

in the

of this, steganography must

be considered when developing a computer security policy.

Although steganography
sense

strictest

it is

not.

is

considered by

covert channel uses

purpose they were not intended

[1].

to

be a form of covert channel,

mechanisms

in a

in the

computer system

for a

For example, the amount of disk storage available can

be modulated by a process operating


level can

many

at

a high security level.

process

at

a lower security

monitor the effects of this modulation and thereby receive information from the

higher security level. In contrast, steganography can exploit a trusted subject's privileges
in a multi-level system. Specifically, those privileges

classification

operator

is

which allow

it

to write to a

lower

domain. In the context of an image downgrading system where a human

using a trusted subject to change the classification of images, steganography

takes advantage of the operator's inability to discern or identify the distortion caused by

embedded
to

data. Since

human

perception

is

not sufficient in this case to prevent flow of data

lower classification domains, additional controls are called

The key
system.

to preventing steganographic exfiltration of data is a strong integrity control

One method which may be used

embedded checksum or message

digest

to protect the integrity of

[4].

image would render the embedded

keys and methods

may need

to

image

files is

an

checksum or message digest would be

computed, encrypted and steganographically embedded


the

for.

in

an image.

integrity seal unrecoverable.

Any tampering

with

(Note that encryption

be protected using a high assurance security policy

enforcement mechanism.)

33

Another method of protecting a system against steganographic

employ anti-steganography measures when handling image


compression,

upon

for

effects

is

to

is

Transform based lossy

It is

possible for

embedded data

of the distortion The amount of data hidden

in

such a

to

be encoded to

way would be

resist the

small compared

of the image due to the large amount of error correcting data which must be

to the information

being embedded.

STEGANOGRAPHIC APPLICATIONS

B.

Steganography

is

a relatively simple concept

are not difficult to develop with

of data

very effective in garbling embedded data, but cannot be relied

complete protection.

to the size

added

JPEG,

e.g.

files

exfiltration

commonly

and implementations of steganography

available tools, e.g.

C++, awk,

shell scripts, etc

competent programmer could write a steganographic application and an accompanying

shell script to

embed

accomplished

in

data to be exfiltrated in

batch

mode

all

image

files

available to him. This could be

to spread out the processing load this

would impose on

system.

The

threat of Trojan horses to system security is well

which handles
the

files.

files

which are

An example

processing,

JPEG

of

suitable for steganography could contain

this is

JPEG

distortion is

code to hide data

applications. Since, in the normal course of

in

its

introduces distortion into an image, a Trojan horse steganography

algorithm would have an extra measure of covertn'ess

image

documented Any application

due entirely to

JPEG

processing

34

i.e.

an observer would assume the

VI.

A.

SUGGESTIONS FOR FURTHER RESEARCH

AN UNEXPLORED DISCIPLINE
As

This thesis explores only a small part of the science of steganography.


discipline, there is a great deal

more research and development


which were offshoots

sections describe areas for research

of,

to do.

new

The following

or tangential

to,

our main

objectives.

Detecting Steganography in Image Files

1.

Can steganography be detected

image

in

files?

This

a difficult question.

is

possible to detect a simple steganographic technique by simply analyzing the

of the image bytes. If the steganographic algorithm


the
it

embedded data over

may be

image

the

in a

random way

If,

amount,

it

24

may

indicate tampering. This theory

bit

two

bits

that

most images use

image, there are a great

low order bits

more complex, however, and spreads

or encrypts the data before embedding,

images may be to examine the colors

many
is

within 2

imperceptible, so a

possible that the original

probably unlikely.

an

based on the idea that most images use a

colors available. If a steganographic technique uses the lower

a particular color

all

in

colors which differ by only a small

of each byte, then any pixel could be changed by

variations of that color


is

in

in a

very small fraction of the 2

value

may be

nearly impossible to detect.

One method of detecting steganography


image.

is

It

at

most a factor of 2

6
.

Assuming

hundreds or thousands of times, there could be 2

values of each other.

clump of colors

like this

this point.

35

would be

image was created with such

A survey of many images from

change

in a pixel's color

suspicious.

Of course,

it is

a fine gradation of color, but this is

various sources could provide insight on

How Widespread

2.

If a

is

the Use of Steganography?

technique or set of techniques could be devised to detect steganography,

it

would

be interesting to conduct a survey of images available on the Internet to determine


steganography

is

used, by

whom, and

available on the Internet, but

it is

not

for

if

what purposes. Steganographic applications are

known

if

they are being used. Moreover, there are

probably other privately developed and used applications in existence.

Steganography on the World Wide

3.

Web (WWW) makes

The World Wide


literally

millions of images on various

an application to serve as a

Web

extensive use of inline images. There are

web pages worldwide.

web browser

to retrieve data

This "stego-web" could operate on top of the existing

It

may be

embedded

possible to develop

in

web page

images.

WWW and be a means of covertly

disseminating information.

Steganography

4.

If data is

embedded

in

Printed Media

in

an image, the image printed, then scanned and stored

in a file,

can the embedded data be recovered? This would require a special form of steganography
to

which could allow for inaccuracies

As was seen

in this thesis,

data. Also, palettization

JPEG garbles

that

when

it

wrapper

file is

in

an image to a smaller subset

unsuitable for steganography

some means may be employed


its

any unencoded steganographically embedded

(mapping a large number of colors

of colors) of an image will render

data

and scanning equipment.

Anti-Steganography Measures

5.

JPEG,

in the printing

processed.

[3]. It is likely,

to prevent loss of steganographically

The question remains open

effective anti-steganography tool or set of tools.

36

as to

what

as with

embedded
is

the most

REFERENCES

LIST OF
1

Amoroso, Edward, Fundamentals of Computer Security Technology,

PTR

Prentice

Hall, 1994.
2.

Brassil,

Low,

J.,

Techniques to

Identification

O'Garman, L., "Electronic Marking and


Discourage Document Copying," IEEE Infocom 94, pp

Maxemchuk,

S.,

N.,

1278-1287.
3.

Cha,

Park,

S.D.,

and Lee, H.K.,

G.H.,

Downgrading Problem,"

in

Applications Conference,
4.

Dorothy

Denning,

Solution

to

the

On-Line Image

Proceedings of the Eleventh Annual Computer Security

New Orleans,

LA,

pp. 108-1 12,

December

1995.

Checksums for Multilevel Database


1984 Symposium on Security and Privacy, 29 Apr - 2

"Cryptographic

E.,

Security," Proceedings of the

5.

"A

May, 1984, Oakland, CA,

pp. 52-61.

Gasser, Morrie, Building

A Secure Computer

System,

Van Nostrand Reinhold,

New

York, 1988.

Group (JPEG) Compression for the National Imagery


Transmission Format Standard, MIL-STD-188-198A, December 1993.

6.

Joint Photographic Experts

7.

Kahn, D.,

8.

Kodak, http://www. kodak. com :80/digitalImaging/samples/varietyPix.shtml.

9.

Kurak,

Codebreakers, MacMillan Company, 1967.

77k?

C, McHugh

J.,

"A

Cautionary Note on Image Downgrading," Proceedings

of the 8th Annual Computer Security Applications Conference, 1992, pp 153-159.


10.

Lockstone, Keith,

"A

USENET newsgroup
11.

12.

Pennebaker,

Class of Steganographic Protocols," Paper posted to the

sci. crypt. research,

William

B.,

Standard,

Van Nostrand

Simmons,

G.J.,

Mitchell,

Reinhold,

29 Nov. 1994.

Joan

L.,

New York,

"The Prisoner's Problem and

JPEG

Still

Image Compression

1993.

the Subliminal Channel,"

Advances

in

Cryptology: Proceedings of Crypto 83, Plenum Press, 1984, pp. 51-67.

Gregory K., "The JPEG Still Picture Compression


Communications of the ACM, Vol. 34, No. 4, April 1991.

13.

Wallace,

14

Walton,

S.,

"Image Authentication

for a Slippery

229, April '95, pp. 18-26.

37

New Age,"

Dr.

Dobbs

Standard,"

Journal, No.

38

APPENDIX: SOURCE CODE


All

A.

code

is

written in

C++

and compiled using the

GNU project C++ Compiler (v2.4)

GENERIC STEGO EMBEDDING PROGRAM

#include <iostream.h>
#include <fstream.h>
#include <math.h>
#include "stegofunctions.h"

/*

21 Feb
infile

This stego program embeds data from a textin

and stores the result as outfile The data

embedded
bits

in the

infile,

//

infile.

infile is the

24

outfile, // outfile is the

textin;

//

bits are

lower density (a user specified parameter)

of each byte of the

fstream

file into a

*/

BMP file

bit

modified 24

textin is the text file to

bit

BMP file

be embedded

in the

char image_file[32], steg_file[32], textsource_file[32];

image

// file

file

names

unsigned char oldtextbyte, hidemask, imagebyte, fullshort, data_hide;


int x,

//

bitsleft;

loop counter

number of bits which have been read from the data


but still need to be embedded in the image file

//
//

unsigned short density, steg_head2,


//

//

in

density at which data

is

file,

embedded, placed

header for use during extraction

textbyte;

unsigned long textbytes,

steghead 1

//

hide,

//

number of bytes in the data file


number of bytes embedded in the image, placed

//

//

in

header to allow for extraction

hold lower density bits of byte to be embedded

fulllong;

bmpheader header;

//

This

is

the current infile header.

39

typedef struct

unsigned short blue, green, red;

color;

Function prototypes

//

void bitslice(unsigned short inbyte, unsigned short bitarray[8]);

void insert_lbit(color& pixel, unsigned short

textbit);

mainO
{

//

read in

names of image

"Enter name of
imagefile;
"Enter name of

"Enter name of

cout

cout
cin

image

file

";
:

the textsource file

";

the output/steg file

";
:

stegfile;

cout

"\n";

Open

cout

the

"\n";

cout

//

file

textsourcefile;

cout

cin

and output

"\n";

cout
cin

file

the input image file and read the header


"\n";

infile.open(image_file, ios::in);

read_bmp_header(infile, header);

cout
cout
cout
cout
cout

cout
cout
cout
cout
cout
cout

cout

"Width: header width

bitcount

imagesize
"Image

"X

"Y

"Number
header numbercolors

"Colors

"Filesize: "
"Offset

bits: "

"Size: "

header. filesize

'\n';

header, offsetbits

header. size

'\n';

'\n';

"

'\n';

"Height: "

"Bit count: "

header.height

'\n';

header.

size: "

'\n';

header.

'\n';

pixels: "

header. x_pixels

'\n';

pixels: "

header.y_pixels

'\n';

colors: "

'\n';

important: "

header. colors_important

"\n";

outfile.open(steg_file, ios: :out);


//

Write the header to the output

file

write_bmp_header(outfile, header);

40

'\n';

//

Now that the header is written, we are

//

bits into the


First,

image bytes

count

as folows:

how many

bytes are in the data

//

//

2.

Embed

//

3.

Read

//

4.

Bitslice the byte into an array of

//

5. Insert the eight data bits into the

the data byte count in the

the output stego

//

is
6.

image

file.

bytes.

in a data byte.

//

//

ready to insert the data

contained

image

its component bits


image bytes and write the bytes to
The number of data bits/image byte

file file.

in the density variable.

Get another

text byte

textin open(textsource_file, ios: :in);

textbytes = bytecount(textin);
"The
has textbytes
"textsource

cout

input text

cout

//

open.\n\n";

file is

Reset the input text

"

file

file

by closing

it

" bytes. \n";

then opening

it.

textin. close();
textin. open(textsource_file, ios::in);

//

cout
cin

density;

bitsjeft

//

which data should be embedded


"Enter the density you would like to use for the embedding >

Prompt the user

Make

8;

//

//

for density at

Embed

density bits per byte

Bits left to

sure the data will

";

embed

fit

((text_bytes*8)/density

+ 25) < header.image_size)

if

//

Embed

//

values will constitute the stego 'header' to allow recovery of the data.

the

number of data bytes

to

be hidden and the density. These

The header will be embeded with a density of 2. (2 is arbitrary)


So a total of 16 + 8 = 24 image bytes will be used for the stego header.
steghead 1 = text_bytes;
steg_head2 = density;

//

//

cout
cout

"\nData

length: "

" Density: "

density

"\n";

for (x=0; x<16;

fulllong =
hide = 3;
hide = hide
//

++x)

//

loop to write the steg_headl value

0;

& stegheadl;
Hide now contains lower 2

fulllong = fulllong
infile

steg_headl

bits

of steg_headl

hide;

read((unsigned char*) &image_byte,

1),

41

'\n';

image_byte = imagebyte

2;

imagebyte = imagebyte
2;
imagebyte = image_byte fulllong;

//

Embed

bits

outfile.write((unsigned char*) &image_byte,

steg_headl = stegheadl

2;

//

1);

get rid of lower 2 bits

for (x=0; x<8;

++x)

//

loop to write the steg_head2 value

full_long=0;
hide
hide

=
=

3;

hide
//

fijlljong

&

steg_head2;

Hide now contains lower 2

= fulllong

bits

of steg_head2

hide;

infile.read((unsigned char*) &image_byte,

imagebyte = imagebyte
imagebyte = imagebyte
2;
=
image_byte image_byte fulllong;

//

1);

2;

Embed

bits

outfile.write((unsigned char*) &image_byte,

steg_head2 = steg_head2

2;

1);

get rid of lower 2 bits

//

hidemask = (unsigned
//

Insert bits into the

while (!textin.eof()

short)

pow(2, (double) density)

image bytes

at the specified

- 1;

density

textbyte =0;

textin.read((unsigned char*) &textbyte,


textbyte
if (bitsleft

textbyte

< density)

//

1); //

Read

a text byte

8;

We must put the leftover bits at the

of the

//

//shift left to

accommodate

new

textbyte

old bits

= textbyte
bitsleft,
textbyte = textbyte old_textbyte; // tack on the old bits
bitsleft = bitsjeft + 8; // The old bits + the new bits

textbyte

while (bitsjeft
fullshort =

>=

density)

0;

datahide = hidemask;
datahide = datahide & textbyte;
// Hide now contains lower density
full

short

full

short

bits

data hide;

42

of textbyte

end

image_byte =

0;

infile.read((unsigned char*) &image_byte,

imagebyte = imagebyte
image_byte = imagebyte
image_byte = image_byte

density;

//

textbyte

bitsleft

Clear lower density bits

density;

full_short;

//

outfile.write((un signed char*)

=
bitsleft =
textbyte

1);

Embed

density bits

&image_byte,

1);

density; //get rid of lower density bits

density;

oldtextbyte = textbyte;

//

save any remaining bits

//End while
// At this point there are less than density bits to embed.
or bitsleft >
// There are two possibilities bitsleft =
// In any case a new textbyte must be read.
//

End while

//

At end of input

file

while (!infile.eof()

so just continue to write pixels without modification,

) {

infile.read((unsigned char*) &image_byte,

1);

outfile.write((unsigned char*) &image_byte,

1);

//End

else

//

data will

fit

cout
}

if

"Data

End

file is

too big to

else data will

fit

into the image. \n";

fit

outfile.close();

textin.closeO;
infile.close();

return 0;

//End of main()

//

This function takes a byte and breaks

//

The

bits are stored in bitarray

it

with the

into its

LSB

component

bits.

in bitarray[0].

void bitslice(unsigned short inbyte, unsigned short bitarray[8])


int

i,

for (i=0; i<8, ++i)


bitarray[i]
if (inbyte

&

0;
1)

bitarray [i]

1;

43

inbyte
}

else inbyte

1;

1;

}//Endofbitslice()

//

This function takes a pixel structure and a text

//

determines which

//

pixel,

// It

the largest color

is

and inserts the

bit in that color

bit,

component of the
component.

hides one bit inside one pixel

void insert_lbit(color& pixel, unsigned short textbit)

unsigned short* big = &pixel.red;


if (pixel. red

else

>=

= &pixel.red;

pixel. green) big

big = &pixel. green;}


if

(*big

<

if (textbit

else

*big
}

pixel. blue) big

*big

1)

= *big

= *big

= &pixel.blue;

*big = *big

1; } //

//End of function

//

Makes

the

1;

Makes

the

LSB

insert_lbit()

44

LSB

B.

GENERIC STEGO EXTRACTION PROGRAM


Stego Extraction Program

/*

21Feb - This version of Extract will extract data hidden at any density
The user will be prompted for the density. If is entered, the
program will try to find the stego header to get the density and
the

number of hidden

(1-7).

*/

bytes.

#include <iostream.h>
#include <fstream.h>

#include <math.h>
#include "stegofunctions.h"
#define PI 3.14159265

fstream

infile,

outfile;

//

//

infile is the

24

bit

BMP file with embedded text

outfile is the extracted text file

char steg_file[32], data_out_file[32];

// file

names

unsigned char stegin, mask, hiddenbyte, inbyte, upper 1, upper2, upper3,


upper4, orphan_bits, densin;

int x;

//

loop counter

unsigned short density, leftoverbits, bytesrecovered;


unsigned long steg_byt.es;

bmpheader header;
typedef struct

//

This

is

the current infile header.

unsigned short blue, green, red;

color;

//

Function prototypes

void bitslice(unsigned short inbyte, unsigned short bitarray[8]);


void insert_lbit(color& pixel, unsigned short textbit);

main()
{

//

Get the name of the input image

//

and the name of the

cout

file in

file

containing stego data (stegfile)

which the extracted data

"\n":

45

will

be stored,

image
"Enter

cout "Enter
name
dataoutfile;
cout

the stego

file

name:

";

stegfile;

cin

for the extracted data: ";

file

cin

infile.open(steg_file, ios::in);

read_bmp_header(infile, header);

cout
cout
cout
cout
cout

cout
cout

cout
cout

cout
cout
cout

"\nStego image

"Filesize:

"Width:
width

bitcount
"Image

imagesize
"X

"Y

"Number

numbercolors
"Colors

colorsimportant
file

"

"Offset

header.file_size

bits: "

"Size: "

information: \n\n";

header.size

"

'\n';

header, offsetbits
'\n';

header.

"Height: "

'\n';

header.height

"Bit count: "

'\n';

'\n',

header.

size: "

'\n';

header.

'\n';

pixels: "

header.x_pixels

'\n';

pixels: "

header.y_pixels

'\n';

colors: "

header.

important: "

'\n';

header.

'\n';

infile.close();

infile.open(steg_file, ios::in);
//

We have reset the

//

stego header.

//

Now we must

//

of hidden data and the density

//

Get the

stego

file

and

now

are ready to read the

extract the stego header consisting of the


at

which

it

number of bytes

was hidden.

number of bytes...

stegbytes =

0; //

stegbytes

for(x=0;x<16;++x)

will contain the

number of hidden bytes

infile.seekg((69 -x), ios::beg);

steg_bytes

steg_bytes

2;

//

Make room

infile.read((unsigned char*) &stegin,

for the next 2 bits

1);

stegin & 3; // Get rid of all bits above the lower two.
stegbytes = steg_bytes stegin; // Put the bits on the bottom of
stegin

//

steg_bytes

now

//

stegbytes

//

Now get the

density

contains the

density

number of hidden bytes

0;

for (x=0; x<8;

++x)

46

in the

image.

infile

seekg((77

density

-x), ios::beg);

density

densin = densin &


density = density
|

Make room

2; //

for the next 2 bits

char*) &densin,

infile. read((unsigned

3; //

Get

densin;

rid

of all

1);

above the lower two.

bits

Put the bits on the bottom of density

//

//

density

cout
cout

cout

//

now

contains the density value of the hidden data

"\nThe hidden
"The hidden

data

is "

steg_bytes

" bytes of dataAn";


" bits per byteAn";

density

"\n";

The stego header

is

now

recovered and stored in stegbytes and density

outfile.open(data_out_file, ios::out);
//
//

data density is "

//

Open

the file that will

hold the extracted data.

We need to be at the first byte containing

stego

bits.

//

The image header and the stego header are contained in the
first 78 bytes so we go to the 79th byte which contains the

//

least significant bit(s)

//

The seekg value

//

infile.

of the

first

byte of the hidden data.

an offset from the

is

file.

seekg(78, ios::beg);

Begin a loop to read


bytes_recovered = 0;
//

leftoverbits

all

the bytes containing data.

0;

while (bytesrecovered < steg_bytes)


switch (density)
case

byte of the

first

//

Density 1111111111111111111111111111111111111111111

mask = 1;
hiddenbyte =

0;

for (x=0; x<8;

++x)

infile. read((unsigned

inbyte

char*) &inbyte,

inbyte

& mask;

hiddenbyte = hiddenbyte (inbyte


|

1),

x);

outfile.write((unsigned char*) &hidden_byte,

1);

-H-bytes_recovered;
break;

case

2:

//

Density 22222222222222222222222222222222222222222222

47

mask = 3;
hiddenbyte =

0;

for (x=0; x<8;

x=x+2)

infile.read((unsigned char*) &inbyte,

= inbyte & mask;


hiddenbyte = hiddenbyte
inbyte

(inbyte
|

1);

x);

outfile.write((unsigned char*) &hidden_byte,

1);

++bytes_recovered,
break;

case

3:

//

Density 33333333333333333333333333333333333333333333

mask = 7,
hiddenbyte =

0;

switch (leftover_bits)
case

0:

infile.read((unsigned char*) &inbyte,

inbyte

= inbyte

&

//

Store the lower 3 bits

hiddenbyte = hidden_byte
//

1);

mask;

inbyte;

Get another byte

infile.read((unsigned char*) &inbyte,

inbyte

= inbyte

&

//

mask;

Store the middle 3 bits

hidden_byte = hidden_byte

(inbyte
|

//

1);

infile.read((unsigned char*) &inbyte,

&

upper2 = inbyte
//

3);

Get another byte


1);

3;

Store the upper 2 bits

hiddenbyte = hidden_byte (upper2


// Orphan bit is bit 2
=
orphanbits inbyte & 4;
leftover_bits = 1;
|

6);

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

case

1:

hidden_byte = orphanbits
//

2; //

Low

stored

infile.read((unsigned char*) &inbyte,

inbyte

= inbyte

&

//

bit

1);

mask;

Store the bits 1,2,3

48

now

hiddenbyte = hiddenbyte (inbyte


|

inbyte

&

= inbyte

hidden_byte = hidden_byte

(inbyte
|

1);

infile.read((unsigned char*) &inbyte,

&

upperl = inbyte

leftover_bits

inbyte

bits

1);

//

4);

1;

// Store the high bit


hidden_byte = hidden_byte (upperl

orphanbits =

1);

mask;

Store the bits 4,5,6

//

char*) &inbyte,

infile. read((unsigned

&

Orphan

6; //

7);

bits are

and 2

2;

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

case

2:

hiddenbyte = orphanbits
//

1; //

Low bit now

stored

infile.read((unsigned char*) &inbyte,

inbyte

&

inbyte

mask;

//Store the bits 2,3,4

hidden_byte = hidden_byte
infile

(inbyte
|

read((unsigned char*) &inbyte,

inbyte

&

= inbyte

//

1);

2);

1);

mask;

Store the bits 5,6,7

hiddenbyte = hiddenbyte (inbyte


leftoverbits = 0;
|

5);

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

default: cout

"\n Invalid leftover Aborting!\n";

return 0;

} //

End of leftover switch

break;

case

4:

//

mask=

Density 44444444444444444444444444444444444444444444

15;

hidden_byte =

0;

infile. read((unsigned

inbyte

= inbyte

&

char*) &inbyte,

1);

mask;

49

hiddenbyte - hiddenbyte (inbyte


|

infile.read((unsigned char*) &inbyte,

inbyte

&

inbyte

4);

1);

mask;

hidden_byte = hidden_byte

inbyte;

outfile.write((unsigned char*) &hidden_byte,

1);

-H-bytesrecovered;
case

5:

//Density 5555555555555555555555555555555555555555555

mask = 31;
hiddenbyte =

0;

switch (leftoverbits)
case

0:

infile.read((unsigned char*) &inbyte,

inbyte

&

= inbyte

1);

mask;

Store the lower 5 bits

//

hiddenbyte = hidden_byte inbyte;


// Get another byte
|

infile.read((un signed char*) &inbyte,

Store the upper 3 bits

//

&

upper3 = inbyte

7;

hiddenbyte - hidden_byte (upper3


orphanbits = (inbyte & 24)
3;
|

//

Orphan

1);

5);

bits are bits 3,4

leftoverbits

2;

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

case

1:

hiddenbyte = orphanbits; //Low

bit

infile.read((unsigned char*) &inbyte,

inbyte

= inbyte

&

//

mask;

infile.read((unsigned char*) &inbyte,

//

stored

1);

Store the bits 1,2,3,4,5

hiddenbyte = hidden_byte (inbyte


upper2 = inbyte

now

1);

1);

& 3;
Store the bits 6,7

hiddenbyte = hiddenbyte (upper2


6);
orphanbits = (inbyte & 28)
2;
// Orphan bits are bits 2,3,4. Right justify
leftover_bits = 3;
|

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;

50

break;

case

2:

hidden_byte = orphan_bits;

Low 2

//

now

bits

stored

infile.read((unsigned char*) &inbyte,

inbyte

Store the bits 2,3,4,5,6

//

hiddenbyte = hidden_byte (inbyte


|

infile.read((unsigned char*) &inbyte,

upper 1 = inbyte

&

Store the bit 7

//

Pull out

orphanbits = (inbyte

1);

//

2);

1;

hiddenbyte = hidden_byte (upper

leftover_bits

1);

& mask;

inbyte

&

orphan
30)

7),

and right justify

bits
1;

4;

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break,

case 3

hiddenbyte = orphanbits;

Low

//

now

3 bits

stored

infile.read((unsigned char*) &inbyte,

&

inbyte = inbyte

1);

mask;

//Store the bits 3,4,5,6,7

hidden_byte = hiddenbyte
leftover_bits

(inbyte
|

3),

0;

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

case

4:

hiddenbyte = orphanbits;
//

Low 4

now

bits

stored

infile.read((unsigned char*) &inbyte,

upper4 = inbyte

&

1);

15;

//Store the bits 2,3,4,5,6

hiddenbyte = hidden_byte (upper4


|

//pull

4);

out orphan bit and right justify

orphanbits = (inbyte
leftover_bits

&

16)

4;

1;

outfile.write((unsigned char*) &hidden_byte,l);

51

it

++bytes_recovered;
break;

default: cout

"\n Invalid leftover. Aborting!\n";

return 0;

} //

End of leftover

switch

break;

case

6:

//Density 666666666666666666666666666666666666666666

mask = 63;
hiddenbyte =

0;

switch (leftoverbits)

case

0:

infile.read((unsigned char*) &inbyte,

inbyte

&

= inbyte

//

Store the lower 6 bits

hiddenbyte = hiddenbyte
//

inbyte;

Get another byte

infile.read((unsigned char*) &inbyte,

upper2 = inbyte

&

1);

mask;

1);

3;
//

Store the upper 2 bits

hiddenbyte = hiddenbyte (upper2


orphan_bits = (inbyte & 60)
2;
// Orphan bits are
leftoverbits = 4;
|

6);

bits 2,3,4,5

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

case

2:

hiddenbyte = orphanbits,
//

Low

2 bits

now

infile.read((unsigned char*) &inbyte,

inbyte

= inbyte

&

mask,
//

//

Store the bits 2,3,4,5,6,7


|

leftover_bits

1),

6 bits

hiddenbyte = hiddenbyte (inbyte

stored

2);

0;

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered,
break;

case

4:

hiddenbyte = orphanbits;

Low 4 bits now

//

infile.read((unsigned char*) &inbyte,

upper4 = inbyte

&

stored
1);

15;
//

Store the bits 4,5,6,7

hiddenbyte = hiddenbyte (upper4


|

//Pull out

orphan_bits = (inbyte
leftoverbits = 2;

orphan

& 48)

4);

bits 4,5

and right justify

it

4;

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

default: cout

"\n Invalid leftover. Aborting!\n";

return 0;

//

End of leftover switch

break;

case

7:

//

mask =

Density 7777777777777777777777777777777777777777777

127;

hidden_byte =

0;

switch (leftover_bits)

case 0:
infile.read((unsigned char*) &inbyte,

inbyte

&

= inbyte

//

Store the lower 7 bits

hiddenbyte = hiddenbyte
//

inbyte;

Get another byte

infile.read((unsigned char*) &inbyte,

upper 1 = inbyte

&

Store the upper bit

hiddenbyte = hiddenbyte (upperl


orphanbits = (inbyte & 254)
1;
// Orphan bits are
|

1);

1;
//

leftover_bits

1);

mask;

7);

1,2,3,4,5,6,7

7,

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

case

7:

hiddenbyte = orphan_bits;
//

Low

7 bits

now

stored

53

infile.read((unsigned char*) &inbyte,

upper 1 = inbyte

&

1);

1;
//

Store the upper bit

hidden_byte = hiddenbyte (upperl


orphanbits = (inbyte & 254)
1;
=
leftoverbits
7;

7);

outfile.write((un signed char*) &hidden_byte,l);

++bytes_recovered;
break;

case

2:

hiddenbyte = orphanbits

Low

bit

//

1;

now

stored

infile.read((unsigned char*) &inbyte,

inbyte

= inbyte

&

1);

mask;
//Store the bits 2,3,4

hidden_byte = hiddenbyte

(inbyte

infile.read((unsigned char*) &inbyte,

inbyte

= inbyte

&

mask;
//

Store the bits 5,6,7

hiddenbyte = hidden_byte (inbyte


|

leftoverbits

2);

1);

5);

0;

outfile.write((unsigned char*) &hidden_byte,l);

++bytes_recovered;
break;

default: cout

"\n Invalid leftover. Aborting !\n";

return 0;

//

End of leftover switch

break;

default:

cout

"Invalid density!

AbortingAn",

return 0,

} //

End

density switch

if (infile.eof()) return 0;
}

//

//

Don't

let

it

go beyond the end of the

End while bytes_recovered

return 0;
}

54

file.

//

This function takes a byte and breaks

//

The

it

with the

bits are stored in bitarray

into

LSB

its

component

bits.

in bitarray[0].

void bitslice(unsigned short inbyte, unsigned short bitarray[8])


inti;

for (i=0; i<8; +-H)

bitarrayfi]
if (inbyte

&

bitarrayfi]

inbyte

else inbyte

0,
1)

1;

1;

}
}

//Endofbitslice()

//

This function takes a pixel structure and a text

//

determines which

//

pixel,

// It

the largest color

is

and inserts the

bit in that color

bit,

component of the
component.

hides one bit inside one pixel.

void insert_lbit(color& pixel, unsigned short textbit)

unsigned short* big = &pixel.red;


if (pixel. red

else

>=

pixel. green) big

&pixel.red;

= &pixel. green,}
if (*big < pixel. blue) big = &pixel.blue;

big

if (textbit

else

*big

//

==

*big

1)

= *big

= *big

1;

= *big

*big

} //

1; } //

Makes

the

1;

Makes

the

LSB

End of function insertlbitQ

55

LSB

C.

IMAGE FILE COMPARISON PROGRAM

#include <iostream.h>
#include <fstream.h>
#include "stego_functions.h"
/* 21

Feb 96
the

This program compares 2 image

Hamming

distance between each pixel.

same

exactly the

displays the

size. It

Hamming

This program

is

produces an error

mapfile;

//

24

//

24

The 2

map

and

file2,

and finds

must be
which

files

file

distances as color coded pixels.

used to look

at the errors

or by a steganographic program.

fstream filel,file2,

files, filel

caused by

JPEG

*/

BMP files to be compared


BMP error map file

bit

bit

char filel [32], file_2[32], errormap[32];

// file

names

unsigned char flbyte_b, flbyte_g, flbyte_r, f2byte_b, f2byte_g, f2byte_r,


//

blue, green

max =
//

int x, y,

OxfT,

and red pixel values for

min = 0x00, mid =

OxOf,

filel

and

white =

file2

Oxff;

color channel values

//

loop counters

number of overall pixels which differ


four_6_diff = 0, seven_9_diff = 0,ten_12_diff =
thirteen_15_diff = 0, sixteen_18_diff = 0, nineteen_21_diff= 0,
twenty two_24_diff = 0;
// number of pixels which differ by these numbers of bits
error_pixels,

//

one_3_diff =

0,

unsigned short diffb, diffr, diff_g,


//

number of bits

differing in each

color channel

intermediatediff, totaldiff;
//

//

0,

//

total

number of bits

differing in

each pixel

bmpheader header l,header2;


//

Function prototypes

unsigned short bits_different(un signed char bytel, unsigned char byte2);

mainO
{

//

read in

cout

names of filel,

file2,

and the errormap

"\n":

56

file

"Enter name of
filel;
"Enter name of

"Enter filename
errormap;

cout
cin

cout
cin

file

#2

";
:

";

for the errormap

cout

//

#1

file_2;

cout
cin

file

";
:

"\n";

Open

filel

and read the header

filel. open(file_l, ios::in);

read_bmp_header(filel, header 1);

cout"File#

:"file_l

'\n';

"Filesize:
headerl

"Offset

"Width: headerl width

"Height: headerl

header
l.bitcount

imagesize
"Image

"X
"Y
headerl

"Number
headerl numbercolors

orsimportant
cout "Colors

"

cout

headerl. file_size

bits: "

cout

"Size: "

cout

headerl. size

'\n';

"

cout

'\n';

'\n';

"

cout

'\n';

offsetbits

height

'\n';

"Bit count: "

cout

'\n';

size: "

cout

headerl.

'\n';

cout

pixels: "

headerl. x_pixels

'\n';

cout

pixels: "

y_pixels

'\n';

colors: "

cout

'\n';

important: "

cout

//

headerl. col

'\n':

"\n";

Open

file2

and read the header

file2.open(file_2, ios::in);

read_bmp_header(file2, header2);

cout
cout

cout
cout
cout
cout
cout
cout

cout
cout
cout
cout
cout

"Width:
width
"Height: header2

header2

"Image
header2.image_size
"X
header2.x_pixels
header2.y_pixels
"Y
"Number
header2.number_colors
"Colors
header2 colorsimportant

"File

"

file_2

"File_size: "

"Offset bits: "


"Size: "

'\n';

header2.file_size

header2.offset_bits

header2.size

"

'\n';

header2.

"

"Bit count: "

'\n';

'\n';

'\n';

height

'\n';

bit_count

'\n';

size: "

'\n';

pixels: "

'\n';

pixels: "

'\n';

colors. "

'\n';

important: "

"\n";

57

'\n':

/*

We are now at the beginning of the pixels


number of pixel bytes

//

Check

if

(header l.imagesize

//

They

to see if the

*/

is

the same,

header2.image_size)

are equal so the comparison can be

made

mapfile open(errormap, ios::out);


//

Write the header to the output

file

write_bmp_header(mapfile, header 1);

= 0;
y < headerl imagesize; y=y+3)

error_pixels
for (y

0;

filel.read((unsigned char*) &flbyte_b,

1);

file2.read((unsigned char*) &f2byte_b,

1);

filel.read((unsigned char*) &flbyte_g,

1);

file2.read((unsigned char*) &f2byte_g,

1);

filel.read((unsigned char*) &flbyte_r,

1);

file2.read((unsigned char*) &f2byte_r,

1);

if

(flbyte_b != f2byte_b)

||

(flbyte^g != f2byte_g)

++error_pixels;

= bits_different(flbyte_b, f2byte_b);
= bits_different(flbyte_g, f2byte_g);
diffr = bits_different(flbyte_r, f2byte_r);
intermediatediff = (diffb + diff_g + diffr);
if (intermediatediff <= 1)
totaldiff = 0;
diff_b

diff_g

else

totaldiff = (intermediate_diff -

1)

3;

switch (totaldiff)
{

//

case

1,2, or 3 bits differ

mapfile. write((unsigned char*)

&min,
mapfile. write((unsigned char*)&max,

mapfile. write((unsigned char*)

&min,

1);

1);
1);

++one_3_diff;
break;
// 4, 5,

case

or 6 bits differ

mapfile. write((unsigned char*)

mapfile. write((unsigned char*)

mapfile. write((unsigned char*)

&max,
&max,

&min,
1);

1);

58

1);

||

(flbyte_r != f2byte_r)

++four_6_diff;
break;
// 7, 8,

case 2

or 9 bits differ
:

mapfile.write((unsigned char*)

mapfile.write((unsigned char*)

&min,

mapfile.write((unsigned char*)

&max,

&max,

1);

1);
1);

++seven_9_diff;
break;
//10, 11, or 12 bits differ

case 3

mapfile.write((unsigned char*) &min,

mapfile.write((unsigned char*)

&max,

mapfile.write((unsigned char*)

&min,

1);

1);

1);

++ten_12_diff;
break,
//

case 4

13, 14, or 15 bits differ

mapfile.write((unsigned char*)

mapfile.write((unsigned char*)

&max,

mapfile.write((unsigned char*)&min,

&max,

1);

1);

1);

++thirteen_15_diff;
break;
//16, 17, or 18 bits differ

case 5

mapfile.write((unsigned char*)

&min,
mapfile.write((unsigned char*) &min,
mapfile.write((unsigned char*)

&max,

1);

1);
1);

++sixteen_18_diff;
break;
//19, 20, or 21 bits differ

case 6

mapfile.write((unsigned char*) &mid,

&mid,
mapfile.write((unsigned char*) &mid,
mapfile.write((unsigned char*)

1);

1);
1);

++nineteen_2 1 _diff;
break;
//22, 23, or 24 bits differ

case 7

mapfile.write((unsigned char*) &min,

&min,
mapfile.write((unsigned char*) &min,

mapfile.write((unsigned char*)

1);

1);
1);

++twentytwo_24_diff,
break;

default
}

cout

"default

bad value

in

switch statement\n";

//end switch

//

end

if

else
{

59

mapfile.write((unsigned char*) &white,


mapfile.write((unsigned char*) &white,

1);

mapfile.write((unsigned char*) &white,

1);

1);

//

end for y

//

The image_size

else

cout

if

statement

"\nThe bitmaps

are of different size. \n";

cout
cout
cout

cout
cout
cout

cout
cout

cout
cout

"There

one_3_diff
by
four_6_diff
6
by
seven_9_diff
9
by
ten_12_diff
by

by
sixteen_18_diff
by
nineteen_21_diff
by
twentytwo_24_diff
by

are "

" pixels

error_pixels

" differ

2,

1,

" differ

" differ

10,

" differ

" differ

" differ

different. \n";

bitsAn";

7,8, or

" differ

thirteen_15_diff

or

4, 5,

" differ

which are

or 3 bitsAn";

1,

bitsAn";

or 12 bitsAn";

13, 14, or 15 bitsAn";

16, 17, or 18 bitsAn";


19, 20, or 21 bitsAn";

22, 23, or

24 bitsAn";

"\n";

mapfile.closeO;
filel.closeO;
file2.close0;

return 0;

//

//

End main()

determine whether bits differ

unsigned short bits_different(unsigned char bytel, unsigned char byte2)

unsigned char xorbyte =

0;

unsigned short count =

0;

xor_byte = bytel A byte2;


for

x=0; x <8; ++x)

count +=(xor_byte

&

xorbyte = xorbyte

{
1 );

return count;

60

D.
/*

RGB VECTOR ENCODING STEGO PROGRAM


Mar 96

19

This version embeds using the modulo-distance-from-origin

technique and repeats each message

Some

bit several times.

variables are defined in the stego functions. h

file.

*/

#include <iostream.h>
#include <fstream.h>
#include <math.h>

#include "stego_functions.h"

fstream infile,

//

24

infile is the

bit

bmp

the modified 24

outfile,

//

outfile is

textin;

//

textin is the text to

file

bit

bmp

file

be hidden

char image_file[32], steg_file[32], textsource_file[32];


//

unsigned char

user-supplied

file

//

variables to hold

names

c, r, g, b,

textbyte,

raw_red, raw_green, rawblue,


nothing;

int

,y, z,

//

//

image

file

bytes

unused byte

loop variables

i,

//

d_mod,

//

vector length modulo

epsilon,

//

stegmodulo
amount of displacement of the pixel along

its

line to origin

repeat,
skip;

//

number of pixels

to skip

between protocol events

number of pixels in the image


number of pixels used to embed data

long total_pixels,//

pixelnum;//

double
t,

dist, //

distance to the origin from the pixel

//

parametric equation variable for computing the pixel's

//

new

position

red, green, blue;

//

the integer versions of the color channels

unsigned long textbytes;

bmpheader header;

//

//

number of bytes

in the text file

the infile header.

61

//

Function prototype

void in_bounds(double& red, double& green, double& blue);

mainO
{

//

read in

names of image

"Enter name of
imagefile;
"\nEnter name of

"Enter name of

cout
cout
cin

the

cout
cin

image

file

";

";

the textsource file

the output/steg file

";

stegfile;

cout

"\n";

Open

cout

file

"\n";

cout

//

and output

textsourcefile;

cout

cin

file

"\n";

image

the input

file

and read the header

"\n";

infile.open(image_file, ios::in);

read_bmp_header(infile, header);

//

Print the

cout
cout
cout

cout
cout
cout

cout
cout
cout

cout
cout

cout

//

image

file's

header data

"Width: header.width

bitcount

imagesize
"Image

header
"X
"Y

"Number
header.numbercolors
"Colors
header.colorsimportant

Open

"File_size: "

"Offset bits: "


"Size: "

header. file_size

'\n';

header, offsetbits

header.size

'\n';

'\n';

"

'\n';

"Height: "

"Bit count: "

header.height

'\n';

header.

size: "

'\n';

header.

'\n';

pixels: "

x_pixels

'\n';

pixels: "

header.y_pixels

'\n';

colors: "

'\n';

important: "

"\n";

the output image file and write

its

header

outfile open(steg_file, ios::out);

write_bmp_header(outfile, header);

62

'\n';

//

Open

the input text file and count the

textin.open(textsource_file, ios:

"The

in

it

:in);

textbytes = bytecount(textin);
cout

number of characters

textbytes

input text file has "

" bytesAn";

textin.closeO;

//Reset the text

file

textin.open(textsource_file, ios:

//

Insert bits into the

image

:in);

pixels.

infile.seekg(header.offset_bits, ios::beg);

//

Make

sure

we

are past the

//file header.

//

Make

sure data will

total_pixels
if

fit

header. width * header.height,

(textbytes* 8 Redundancy >

cout

"Input

data

file is

total _pixels)

too big! Aborting. \n";

return 0;
}

Compute skip factor, skip is the number of pixels to skip


= (header. width*header. height) / ((text_bytes*8)*redundancy);
skip = skip - 3;
if (skip < 0) skip = 0;
"Skip = "
skip
cout
'\n';

//

skip

pixelnum =

0;

while (!textin.eof()

) {

//loop until the text file

textin.read((unsigned char*) &textbyte,

for (x=0; x<8;

++x)

//Embed

all

is

1); //

Read

//

Read

a text byte

8 bits of the text byte

for (repeat=0; repeat<redundancy; ++repeat)

//

empty

//

Embed

Redundancy times

the 3 bytes of a pixel

infile.read((unsigned char*) &raw_red,

1);

infile.read((unsigned char*) &raw_green,


infile.read((unsigned char*) &raw_blue,

1);

1);

++pixelnum;

63

each

bit

//

Convert the values to integers

= rawred;
green = raw_green;
blue = rawblue;
red

//

Make

sure no value

clear of the upper and lower

is

bounds

in_bounds(red, green, blue);

Compute the distance from the origin


dist = sqrt((double)(red*red + green*green +
dmod = ((int) dist) % stegmodulo;

//

needs to slide and

blue*blue));

how much.

//

Find out

//

Set the values of the

//

value which will be written to the stego image

if (textbyte

if

if the pixel

&

) {

//

raw color variables

Embed

(dmod == encodel)

to the
file.

epsilon

0;

else
if

(dmod < encodel

&& dmod >= encodeO)

epsilon

= encodel

else
if

(dmod > encodel)

else
if

epsilon

= -l*(d_mod

epsilon

= -l*(lo_to_hi + dmod);

encodel);

(dmod < encodeO)

else

// 1 is
//

the variable in the parametric equations for

the line on

which the

pixel

t = ((double) epsilon )/dist,


// Compute the new values
red = red + red*t;
green = green + green *t;
blue = blue + blue*t;

lies,

for the pixels

}//Endif
else

if

//

Embed

(dmod == encodeO)

epsilon

0;

else

64

dmod;

if

(d_mod > encode_0

&& dmod <= encodel) epsilon = -l*(d_mod

else
if

(dmod > encodel)

epsilon

= (encode_0 + (stegmodulo

dmod));

else
if

(dmod < encodeO) epsilon = (encodeO - dmod);

else

// 1 is
//

the variable in the parametric equations for

which the

the line on

pixel lies.

t = ((double) epsilon )/dist;


// Compute the new values
red = red + red*t;
green = green + green*t;
blue = blue + blue*t;

//

for the pixels

end else

rawred = (unsigned char) red; // Real


raw_green = (unsigned char) green;
raw_blue = (unsigned char) blue;

value

outfile. write

((unsigned char*) &raw_red,

outfile. write

((unsigned char*) &raw_green,

outfile. write

((unsigned char*) &raw_blue,

//

truncated on conversion

is

1);
1);

1);

//End of 'repeat redundancy times' loop


Skip some pixels between embedded bits

for (z=0; z<skip;

++z)

infile.read((unsigned char*) &raw_red,

1);

infile.read((unsigned char*) &raw_green,


infile.read((unsigned char*) &raw_blue,

1);

1);

++pixelnum;

outfile. write

((unsigned char*) &raw_red,

outfile. write

((unsigned char*) &raw_green,

outfile. write

((unsigned char*) &raw_blue,

//forz

textbyte

65

1);

1),

1);

encodeO);

//

embed

for x to

end while

} //

//

End

8 bits

textin.eofQ

At end of input

file

while (!infile.eof()

so just continue to write pixels without modification,

infile.read((unsigned char*) &raw_red,

1);

infile.read((unsigned char*) &raw_green,


infile.read((unsigned char*) &raw_blue,
if (!infile.eof())

1);

1);

outfile. write

((unsigned char*) &raw_red,

outfile. write

((unsigned char*) &raw_green,

outfile. write

((unsigned char*) &raw_blue,

1);
1);

1);

cout

pixelnum

"Pixels used: "

'\n';

outfile.close();

textin.closeO;
infile.close();

return 0,

//

End of main()

void in_bounds(double& red, double& green, double& blue)

//

This function checks to

//

in

if (red

else

> hibound)

< lobound)

(green

else

red

is

sure the color values are

adjusted to be in bounds.

= hibound;

if (red

if

make

bounds. If not the value

red

= lobound;

> hibound) green = hibound;

66

if

(green

if (blue

else

//

> hi_bound) blue = hibound;

if (blue

< lo_bound) green = lo_bound;

< lo_bound) blue = lobound;

end in_bounds

67

RGB VECTOR STEGO EXTRACTION PROGRAM

E.
/*

This version of extract will extract data hidden by modifying


the

modulus of the distance from the

origin.

This version

uses a user supplied skip factor.

Some

variables are defined in the stegofunctions.h

file.

*/

#include <iostream.h>

#include <fstream.h>
#include <math.h>
#include "stegofunctions.h"
fstream

infile,

outfile;

//

//

24

infile is the

outfile is the

bmp file
bmp file

bit

modified 24

bit

char steg_file[32], data_out_file[32];


//

file

unsigned char hiddenbyte,

//

//

variables for the user-supplied

names
the byte of data being recovered

raw_red, raw_green, rawblue,// image

file

bytes

nothing;// unused byte

unsigned char
int x,y,z,i, //

c,

r,

g, b;

loop variables

red, green, blue,

//

integer versions of the color values

d_mod,// distance to origin modulo steg_modulo


skip;

double

//

number of pixels

to skip

between protocol events

dist;

unsigned short bytes_recovered;

unsigned long hiddenbit,


long pixelnum;

//

//

//

count of bytes recovered so far

holds the bits representing the hidden

number of pixels used

in the

bit

recovery process

unsigned long steg_bytes=0;

bmpheader header;
//

//

This

is

the current infile header.

Function prototype

int

byteweight(unsigned long hbyte);


//

//

Counts the number of

long variable

68

's in

an unsigned

mainQ
{

//
//

Get the name of the input image file containing stego data (stegfile)
and the name of the file in which the extracted data will be stored.

name:
image
"Enter

"Enter name

=
"\nThe
be
based on mod62\n";
"How many
hidden?
stegbytes;

"What

cout

"\n";

the stego

cout
cin

steg_file;

cout
//

cin

for the extracted data: ";

file

data_out_file;

data_out_file

"steg.out";

cout

data will

extracted

";

bytes are

cout
cin

";

file

cout

'\n';

//

cout

//

cin

the skip factor?

is

";

skip;

skip =17;

cout

'\n';

infile.open(steg_file, ios::in);

read_bmp_header(infile, header);

cout
cout

cout
cout

cout
cout
cout
cout
cout
cout
cout

cout

"\nStego image
"Filesize:

"Width:
width

bitcount

"Image

image_size
"X

"Y

"Number

number_colors
"Colors

colorsimportant
file

"

"Offset bits: "


"Size: "

information: \n\n";

header, filesize

header, offsetbits

header. size

"

'\n';

header.

"Height: "

'\n';

header.height

"Bit count: "

'\n';

'\n';

'\n';

header,

size: "

'\n';

header.

'\n';

pixels: "

header.x_pixels

'\n';

pixels: "

header.y_pixels

'\n';

colors: "

important: "

header.

'\n';

header.

cout'\n';

infile.close();

infile.open(steg_file, ios::in);

outfile open(data_out_file, ios::out);


//

//

Open

the file that will

hold the extracted data.

69

'\n';

//

We need

//

The image header

// first

to

be

at the first

54 bytes so

is

contained

we go

//

least significant bit(s)

//

The seekg value

is

byte of the

first pixel.

in the

to the 55th byte

of the

first

which contains the

byte of the hidden data.

an offset from the

first

byte of the

file.

infile.seekg(header.offset_bits, ios::beg);

//

Begin a loop to read

bytes_recovered

pixelnum =

all

the bytes containing data.

0;

0;

while (bytesrecovered < stegbytes)

hiddenbyte =

0;

++x) { // Loop 8 times to recover byte of hidden data


hiddenbit = 0;
for (y=0; y<redundancy; ++y) { // Loop redundancy # times to get one

for (x=0; x<8;

//

Read

a pixel

infile.read((unsigned char*) &raw_red,


infile

1);

read((unsigned char*) &raw_green,

infile.read((unsigned char*) &raw_blue,

1);

1);

++pixelnum;
//

Convert the values to integers

rawred;
=
green
(int) raw_green;
blue = (int) rawblue;
red

//

(int)

Compute

the distance from the origin

dist = sqrt((double)(red*red + green*green + blue*blue));


dmod = ((int) dist) % steg_modulo;

if

(dmod >

pivot) hidden_bit |= (1

y);

else;
}

//

//Fory

Skip some pixels after each


for (z=0, z<skip;

++z)

bit is

read

70

bit

infile.read((unsigned char*) &nothing,

1);

infile.read((unsigned char*) &nothing,

1);

infile.read((unsigned char*) &nothing,

1);

++pixelnum;

if

//forz

(byteweight(hiddenbit) > (int)(redundancy/2)) hidden_byte

|= (1

x);

else;

//End of x loop

outfile.write((unsigned char*) &hidden_byte,

1);

++bytes_recovered;
if (infile.eof()) return 0;
//

//

Don't

let

it

go beyond the end of the

file.

End while bytes_recovered

cout

"Pixels used: "

pixelnum

'\n';

infile.close();

outfile closeQ;

return 0;

II*

int

************************************************************
byteweight(unsigned long hbyte)

int x,

w;

w=0;
for(x=0;x<15;++x) {
if (hbyte & l)++w;
hbyte

return w;
}

71

STEGO FUNCTIONS HEADER FILE

F.

This

//

is

the stegofunctions.h file

#include <fstream.h>

struct

bmpheader

char bm[2];

//

//

This structure holds the 24

header information. There

is

no

bit

bmp

pallette

unsigned long filesize;// data.


unsigned short reserved[2];
unsigned long
offset_bits,
size,

width,
height;

unsigned short
planes,

bit_count;

unsigned long
compression,

imagesize,
x_pixels,
y_pixels,

numbercolors,
col orsi important;
};

int

//

redundancy =

5; //

the

number of times

modulo parameters
stegmodulo = 62,
pivot = 30, // Anything over 30
encodel = 47,
encode_0 = 1 6,
hibound = 224,
lobound = 31,
lo_to_hi = 15;

to

embed

a bit

Set the

int

is

stegmodulo = 42, commented out


pivot = 20, // Anything over 20 is a
encodel =31,
encodeO = 10,
hi_bound = 235,
lo bound = 20,

/*int

since

72

we

are using

steg_modulo=62

lo_to_hi

//

11;*/

Function prototypes

bmpheader& header);
void write_bmp_header(fstream& outfile, bmpheader& header);
void read_bmp_header(fstream&

long

int

byte_count(fstream&

infile,

intext);

unsigned long read_lsbfirst_long(fstream&

infile);

unsigned short read_lsbfirst_short(fstream&

infile);

void write_lsblongfirst(fstream& outfile, unsigned long value);


void write_lsbshortfirst(fstream& outfile, unsigned short value);

bmp

format was designed for dos based machines.

//

The
The
The
The

//

values to and from big endian variables.

//

This function reads a

//
//

//

file

values of the header are stored in

endian format.

little

stego programs were developed on big endian workstations.

functions below read and write these

//which

is

bmp

little

endian

header into a bmpheader structure

passed by reference.

void read_bmp_header(fstream&

infile,

bmpheader& header)

infile. read((unsigned

char*) &header.bm[0],

1);

infile. read((unsigned

char*) &header.bm[l],

1);

header, filesize

read_lsbfirst_long(infile);

= read_lsbfirst_short(infile);
header. reserved[l] = read_lsbfirst_short(infile);
header, offsetbits = read_lsbfirst_long(infile);
header. size = read_lsbfirst_long(infile);
header. reserved[0]

header, width

readjsbfirstlong(infile);

= readlsbfirstjong(infile);
header.planes = read_lsbfirst_short(infile);
header.bitcount = readjsbfirstshort(infile);
header. compression = read_lsbfirst_long(infile);
header. imagesize = readjsbfirstjong(infile);
header. x_pixels = readjsbfirstjong(infile);
header. y_pixels = readjsbfirstjong(infile);
header. numbercolors = read_lsbfirst_long(infile);
header. colorsimportant = read_lsbfirst_long(infile);
} // End of readbmpheaderO
header. height

/*

//

***********************************************************

This function writes a

bmp

header to a

file.

73

void write_bmp_header(fstream& outfile,

bmpheader& header)

outfile. write((unsigned

char*)&header.bm[0],

outfile. write((unsigned

char*) &header.bm[l], sizeof(header.bm[l]));

1);

write_lsblongfirst(outfile,header.file_size);

write_lsbshortfirst(outfile,header.reserved[0]);
write_lsbshortfirst(outfile,header.reserved[l]);
write_lsblongfirst(outfile,header.offset_bits);

write_lsblongfirst(outfile,header.size);

write_lsblongfirst(outfile,header. width);

write_lsblongfirst(outfile,header.height);
write_lsbshortfirst(outfile,header. planes);

write_lsbshortfirst(outfile,header.bit_count);
write_lsblongfirst(outfile,header. compression);

write_lsblongfirst(outfile,header.image_size);
write_lsblongfirst(outfile,header.x_pixels);
write_lsblongfirst(outfile,header.y_pixels);

write_lsblongfirst(outfile,header.number_colors);
write_lsblongfirst(outfile,header.colors_important);
//

End of write_bmp_header()

long

int

byte_count(fstream& intext)

//

This function counts the number of bytes in a

//

returns the count as a long integer,

int

count =

while

(!

file

0;

intext. eof())

(void) intext. getO;

++count,
}

return count;
} //

//

End of byte_count

Read

little

endian long integer

unsigned long read_lsbfirst_long(fstream&

infile)

unsigned char buffer[4];


unsigned long value;
infile. read((unsigned

char*) &buffer, 4);

value = (unsigned long)

(buffer[3]

24);

74

and

value

|=

(unsigned long) (buffer[2]

value

|=

(unsigned long) (buffer[l]

value

|=

(unsigned long) (buffer[0]);

16);
8);

return value;

//

//

End of unsigned long

Read

little

endian short integer

unsigned short read_lsbfirst_short(fstream&

infile)

unsigned char buffer[2];

unsigned short value;


infile. read((unsigned

value = (unsigned

value

|=

char*) &buffer, 2);

short) (buffer[l]

8);

(unsigned short) (buffer[0J);

return value;

//

End of unsigned

short

Back up one byte/


infile. write((unsigned char*) &new_c, 1); */
/*infile.seekg(-l, ios::cur);

//

Write a

little

endian long integer

void write_lsblongfirst(fstream& outfile, unsigned long value)

unsigned char
buffer[4];

buffer[0]
buffer[l]
buffer[2]
buffer[3]

=
=
=
=

(unsigned char) (value);


(unsigned char) ((value)
(unsigned char) ((value)
(unsigned char) ((value)

outfile. write((unsigned

8);

16);

24);

char*) &buffer, 4);

75

//

//

End of unsigned long

Write a

little

endian short integer

void write_lsbshortfirst(fstream& outfile, unsigned short value)

unsigned char
buffer[2];

buffer[0]
buffer[l]

= (unsigned
= (unsigned

char) (value);

8);

char*) &buffer,

2);

char) ((value)

outfile. write((unsigned

//End of unsigned short

//

76

INITIAL DISTRIBUTION LIST


1.

Defense Technical Information Center


8725 John J. Kingman Rd STE 0944
Ft. Bel voir, VA 22060-6218

Dudley Knox Library

2.

Naval Postgraduate School


411 DyerRd.

Monterey,
3.

CA

Chairman, Code

93943-5101

CS

Computer Science Department


Naval Postgraduate School
Monterey,
4.

Raymond

CA

93943
2

I shell

Central Imagery Office

8401 Old Courthouse Road


Vienna,

5.

VA 22182-3280

Dr. Blaine

Burnham
Agency

National Security

Research and Development Building

R23
9800 Savage Road
20755-6000

Fort Meade,

6.

MD

William Marshall

Agency
Research and Development Building
R23
9800 Savage Road
National Security

Fort Meade,

7.

MD 20755-6000

Dr Cynthia E. Irvine
Computer Science Department
Code CS/Ic
Naval Postgraduate SchoolMonterey,

15

CA 93943-51 18

77

8.

9.

Dr. Harold Fredricksen


Mathematics Department, Code
Naval Postgraduate School
Monterey, C A 93943-51 18

Commanding

MA/FS

Officer

Fleet Information Warfare Center

2555 Amphibious Drive


Little Creek
Norfolk, VA 23521-3225

NAB

10.

Naval Information Warfare Activity

ATTN:

CDR J

O'Dwyer

9800 Savage Road


20755-6000

Fort Meade,

1 1

MD

LT Hannelore Campbell
USS Boxer (LHD 4)

FPOAP 96661
12.

LT

Daniel

Currie

III

Fleet Information Warfare Center

2555 Amphibious Drive


NAB Little Creek
Norfolk, VA 23521-3225

78

:00L
:Y

CA 9394^101

DUDLEY KNOX LIBRARY

3 2768 00322410 6

You might also like