...

Implementation and efficiency of steganographic techniques in bitmapped images and embedded

by user

on
Category: Documents
10

views

Report

Comments

Transcript

Implementation and efficiency of steganographic techniques in bitmapped images and embedded
Calhoun: The NPS Institutional Archive
Theses and Dissertations
Thesis and Dissertation 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
1
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
L
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.
A
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
1
A.
1.
1
1
3
Subliminal Communication
2.
Integrity
3.
Illicit
3
and Authentication
3
4
Exfiltration
D
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
F
VI
10
[10]
1
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.
V
10
Bit Insertion
A.
EMBEDDED MESSAGE SURVIVABILITY
A
IMAGE PROCESSING ISSUES
B
JPEG COMPRESSION
JPEG EFFECTS ON IMAGE DATA
C
D
8
2.
1.
IV
7
1.
2.
HI
5
7
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
A
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
a
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
A
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.
A
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
A
[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.
a
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
a
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.
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.
A
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
1
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
a
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
I
Wrapper
Pixels
Pixel
I
Message
Pixel 2
1
Pixel 3
|i|o|l|l|l
Bits
Transmitted
Steganographed
Pixels
Pixel
Figure
Figure
of 8
1
1:
demonstrates
bit pixels
Direct Insertion of Message Bits
how
a
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
1
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
1
to
W*H, where
defined
as
a
W
file
every pixel p where p
suitable as long as
it
mod
2
is
mathematical
selects
Another PES method
equal to
linear
function
to
A
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
a
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
1
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
a
1.
Message
1
1
Bits
Original
1
1
Insertion
Insertion
Insertion
Point
Point
Point
10;
1
1
1
1
1
1
1
1;
N
1
—
10
1
Wrapper
Pixels
Pixel
I
1
Pixel 2
I
Pixel 3
|
Transmitted
Steganographed
Pixels
1
1
l|l
1
Pixel
Figure
3:
1
1
1
1
1
Pixel 2
I
Bit Inversion
12
the message
1
|
1
1
1
Pixel 3
1
1
|
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
1
Pixel
Figure
The message
where
a bit differs
when
the
is
]
Pixel 2
10
1
I
Pixel 3
11
110
Pixel 3
Pixel 2
1
Bit Insertion
extracted by comparing the wrapper with the stegotext and noting
and
message
4:
1
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
1
is
to
is
to
be inserted, a 01 pair
is
is
chosen and the
chosen and the
1
of the pair
of the pair
is
is
deleted.
Message
Bits
Original
1
1
Insertion
Insertion
Insertion
Point
Point
Point
ijo[i!
1
1
1
1
Wrapper
Pixels
1
Transmitted
Steganographed
Pixels
Pixel
1
1
Pixel
Figure
Again, the message
stegotext.
is
5:
Pixel 2
1
1
100
11
1
1
1
1
100 jmoil
Pixel 3
|
iolo
Pixel 2
I
1
1
|
1
00
1
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
I
Pixel
1
Pixel 2
I
|
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
1
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
1
Insertion
Insertion
Insertion
Point
Point
Point
10
1
100
1
1
Wrapper
Pixels
Pixel
1
Transmitted
Steganographed
wrapper
file
Flag
Bit
Bit
1
1
1
1
10
1
1
1
100
Pixel 2
1
0|1
Pixel 3
I
Flag
1
10
1
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
1
Bit
Figure
F.
Pixel 2
1
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
1
1
1
1
1
1
1
1
\
10 0l|l
1
oil
Wrapper
Pixels
Pixel
I
Pixel 2
1
«V
Transmitted
Steganographed
1
1
this
requires the
1
8:
1
1
1
1
1
Pixel 2
I
example, odd parity represents
PES
1
1
1
|
1
1 1
1
Pixel 3
|
Neighbor Parity
1
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
1
3)
Figure
For
1
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
*
H
*
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
/
D
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
A
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
A
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
A
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
a
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]
1
1
in
..'
'
•
;
:'.•
^
•'
^
J
t
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
a
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
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
1
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
8
7
6
5
4
3
2
1
Glasses
744
4032
10247
21273
33644
42327
27196
48554
Seagull
257
99)
2821
7514
15039
29941
41593
46640
Table
Table
shows
2
corresponding pixels
1
:
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
4
Seagull
24188
38710
17564
4631
409
43
1
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
r
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
1
,<.
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
1
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
1
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
a
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
a
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
1
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
A
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
r
=
:
+ 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
B
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,
8
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)
3
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.
A
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.
A
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].
A
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
A
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
a
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
a
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
2
would be
image was created with such
A survey of many images from
A
change
6
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
//
1
//
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
I
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
|
1
;
}
//
Makes
the
1;
Makes
the
LSB
insert_lbit()
44
LSB
1
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
a
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
1
:
//
{
{
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
1
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);
«
1
|
//
2);
1;
hiddenbyte = hidden_byte (upper
leftover_bits
1);
& mask;
inbyte
&
orphan
30)
»
i
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
1
»
}
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
1
{
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
a
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
1
«
'\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
"
2
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
1
:
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
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 );
»
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
x
,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
&
1
) {
//
raw color variables
Embed
(dmod == encodel)
a
to the
file.
1
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
a
(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
»=
1
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
1
'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
//
a
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
1
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
»=
1
}
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
a
is
1
stegmodulo = 42, commented out
pivot = 20, // Anything over 20 is a
encodel =31,
encodeO = 10,
hi_bound = 235,
lo bound = 20,
/*int
since
1
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
I
/*
//
***********************************************************
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
a
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
a
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
2
Dudley Knox Library
2
,
2.
Naval Postgraduate School
411 DyerRd.
Monterey,
3.
CA
Chairman, Code
93943-5101
CS
2
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
2
National Security
Research and Development Building
R23
9800 Savage Road
20755-6000
Fort Meade,
6.
MD
William Marshall
2
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
L
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
Fly UP