├── .gitignore ├── Algorithme.pdf ├── Package Steganography.png ├── README.md ├── Screenshot.png ├── StegIt.jar ├── _config.yml ├── documentation ├── Steganography │ ├── Controller.html │ ├── Exceptions │ │ ├── CannotDecodeException.html │ │ ├── CannotEncodeException.html │ │ ├── UnsupportedImageTypeException.html │ │ ├── class-use │ │ │ ├── CannotDecodeException.html │ │ │ ├── CannotEncodeException.html │ │ │ └── UnsupportedImageTypeException.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ ├── Logic │ │ ├── AESEncryption.html │ │ ├── BaseSteganography.html │ │ ├── GifSequenceWriter.html │ │ ├── GifSteganography.html │ │ ├── HiddenData.html │ │ ├── ImageInImageSteganography.html │ │ ├── ImageSteganography.html │ │ ├── Metadata.html │ │ ├── Utils.html │ │ ├── ZLibCompression.html │ │ ├── class-use │ │ │ ├── AESEncryption.html │ │ │ ├── BaseSteganography.html │ │ │ ├── GifSequenceWriter.html │ │ │ ├── GifSteganography.html │ │ │ ├── HiddenData.html │ │ │ ├── ImageInImageSteganography.html │ │ │ ├── ImageSteganography.html │ │ │ ├── Metadata.html │ │ │ ├── Utils.html │ │ │ └── ZLibCompression.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ ├── Main.html │ ├── Modals │ │ ├── AboutPage.html │ │ ├── AlertBox.html │ │ ├── PasswordPrompt.html │ │ ├── class-use │ │ │ ├── AboutPage.html │ │ │ ├── AlertBox.html │ │ │ └── PasswordPrompt.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ ├── Types │ │ ├── DataFormat.html │ │ ├── PasswordType.html │ │ ├── class-use │ │ │ ├── DataFormat.html │ │ │ └── PasswordType.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ ├── class-use │ │ ├── Controller.html │ │ └── Main.html │ ├── package-frame.html │ ├── package-summary.html │ ├── package-tree.html │ └── package-use.html ├── allclasses-frame.html ├── allclasses-noframe.html ├── constant-values.html ├── deprecated-list.html ├── help-doc.html ├── index-files │ ├── index-1.html │ ├── index-10.html │ ├── index-11.html │ ├── index-12.html │ ├── index-13.html │ ├── index-14.html │ ├── index-15.html │ ├── index-16.html │ ├── index-17.html │ ├── index-18.html │ ├── index-19.html │ ├── index-2.html │ ├── index-20.html │ ├── index-21.html │ ├── index-22.html │ ├── index-23.html │ ├── index-3.html │ ├── index-4.html │ ├── index-5.html │ ├── index-6.html │ ├── index-7.html │ ├── index-8.html │ └── index-9.html ├── index.html ├── jquery │ ├── external │ │ └── jquery │ │ │ └── jquery.js │ ├── images │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_454545_256x240.png │ │ ├── ui-icons_888888_256x240.png │ │ └── ui-icons_cd0a0a_256x240.png │ ├── jquery-1.10.2.js │ ├── jquery-ui.css │ ├── jquery-ui.js │ ├── jquery-ui.min.css │ ├── jquery-ui.min.js │ ├── jquery-ui.structure.css │ ├── jquery-ui.structure.min.css │ ├── jszip-utils │ │ └── dist │ │ │ ├── jszip-utils-ie.js │ │ │ ├── jszip-utils-ie.min.js │ │ │ ├── jszip-utils.js │ │ │ └── jszip-utils.min.js │ └── jszip │ │ └── dist │ │ ├── jszip.js │ │ └── jszip.min.js ├── member-search-index.js ├── member-search-index.zip ├── overview-frame.html ├── overview-summary.html ├── overview-tree.html ├── package-list ├── package-search-index.js ├── package-search-index.zip ├── resources │ ├── glass.png │ └── x.png ├── script.js ├── search.js ├── serialized-form.html ├── stylesheet.css ├── type-search-index.js └── type-search-index.zip ├── src ├── META-INF │ └── MANIFEST.MF └── Steganography │ ├── Controller.java │ ├── Exceptions │ ├── CannotDecodeException.java │ ├── CannotEncodeException.java │ ├── UnsupportedImageTypeException.java │ └── package-info.java │ ├── Logic │ ├── AESEncryption.java │ ├── BaseSteganography.java │ ├── GifSequenceWriter.java │ ├── GifSteganography.java │ ├── HiddenData.java │ ├── ImageInImageSteganography.java │ ├── ImageSteganography.java │ ├── Metadata.java │ ├── Utils.java │ ├── ZLibCompression.java │ └── package-info.java │ ├── Main.java │ ├── Modals │ ├── AboutPage.java │ ├── AlertBox.java │ ├── PasswordPrompt.java │ └── package-info.java │ ├── Resources │ ├── layout.fxml │ ├── logo.png │ ├── modena_dark.css │ ├── package-info.java │ └── stylesheet.css │ ├── Types │ ├── DataFormat.java │ ├── PasswordType.java │ └── package-info.java │ └── package-info.java └── testFiles ├── ENSI.jpg ├── cat.gif ├── colors.gif ├── cute.gif ├── fuck.gif ├── gatsby.jpg ├── gatsby.txt ├── giphy.gif ├── hello.txt ├── human.gif ├── image.png ├── image2.png ├── leo.gif ├── lol.png ├── merc.bmp ├── ohno.gif ├── shakespeare.txt ├── test.rtf ├── test.txt └── testar.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | encoded.* 3 | secret* 4 | .DS_Store 5 | info 6 | text -------------------------------------------------------------------------------- /Algorithme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/Algorithme.pdf -------------------------------------------------------------------------------- /Package Steganography.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/Package Steganography.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StegIt 2 | 3 | > The word “steganography” can be defined as “covered writing” or the technique of hiding messages inside other messages. It is derived from a Greek word “στεγαυω”. This idea of data hiding is not a novelty, it has been used for centuries all across the world under different regimes - but to date it is still unknown to most people - is a tool for hiding information so that it does not even appear to exist. 4 | 5 |  6 | 7 | ### An image steganography application to hide text, documents or images in images. 8 | 9 | StegIt uses the Least Significant Bit (LSB) algorithm to hide the secret data in the least significant bits of each RGB components of an image in a way that will be invisible to the naked eye 10 | 11 | ##### Authors: [Feres Gaaloul](https://github.com/feresg), [Ilyes Hamrouni](https://github.com/ilyes-hamrouni) 12 | ##### ENSI Summer Project. 13 | 14 | #### Features: 15 | - Use 24 bit bitmap `PNG`, `BMP` and `JPG` images and also animated `GIF` images as cover image. 16 | - Hide text, documents and 24 bit bitmap images as secret data. 17 | - Compress data before encoding to reduce effect on stego image using the `Java ZLib` compression library. 18 | - Encrypt the secret message or document using `128 bit AES CBC` encryption (Advanced Encrytion Standard) for an added layer of security. 19 | - Provide either a password for encryption, or an image that will be automatically hashed to create an encryption key. 20 | - Choose the number of pixels to use to hide 1bit of data/1 pixel (1 or 2). 21 | - Interaction with system applications and clipboard. 22 | 23 | #### Environment : 24 | This application is built using `Java` and `JavaFX` for GUI development. 25 | 26 | #### Requirements: 27 | `Java JDK` is required to build the project, `Java JRE` is required to run the project. 28 | 29 | #### Notes: 30 | - Tested working document formats : 31 | - Working : any plain text documents ( `.txt`, `.log`, `.java`, `.py`, `.cpp`, `.html`, `.xml`). and rich format documents (`.rtf` , `.doc` (with basic formatting)) and `.pdf` documents. 32 | - Not Working : `.docx`. 33 | 34 | #### Issues: 35 | - Cover `JPG` images are saved as `PNG` to avoid loss of hidden data after JPEG compression. 36 | - Due to the limitation of the `GIF` colormap, hiding large data can heavily alter images. 37 | 38 | #### Project Structure: 39 | - __src__ : source files. 40 | - __testFiles__ : images and documents used to test the app. 41 | - __documentation__ : `JavaDoc` documentation of the project. 42 | - __StegIt.jar__ : Binary application. 43 | - __Screenshot.png__ : main screenshot. 44 | - __Package Steganography.png__ : `UML` class diagram. 45 | - __Algorithme.pdf__ : project, GUI and algorithms description (in french). 46 | 47 | 48 | -------------------------------------------------------------------------------- /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/Screenshot.png -------------------------------------------------------------------------------- /StegIt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/StegIt.jar -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /documentation/Steganography/Exceptions/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |37 | 38 | 39 | -------------------------------------------------------------------------------- /documentation/package-list: -------------------------------------------------------------------------------- 1 | Steganography 2 | Steganography.Exceptions 3 | Steganography.Logic 4 | Steganography.Modals 5 | Steganography.Types 6 | -------------------------------------------------------------------------------- /documentation/package-search-index.js: -------------------------------------------------------------------------------- 1 | packageSearchIndex = [{"l":"Steganography"},{"l":"Steganography.Exceptions"},{"l":"Steganography.Logic"},{"l":"Steganography.Modals"},{"l":"Steganography.Types"}] -------------------------------------------------------------------------------- /documentation/package-search-index.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/documentation/package-search-index.zip -------------------------------------------------------------------------------- /documentation/resources/glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/documentation/resources/glass.png -------------------------------------------------------------------------------- /documentation/resources/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/documentation/resources/x.png -------------------------------------------------------------------------------- /documentation/script.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. 3 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 | * 5 | * 6 | * 7 | * 8 | * 9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | */ 25 | 26 | var moduleSearchIndex; 27 | var packageSearchIndex; 28 | var typeSearchIndex; 29 | var memberSearchIndex; 30 | var tagSearchIndex; 31 | function loadScripts(doc, tag) { 32 | createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); 33 | createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); 34 | if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || 35 | window.navigator.userAgent.indexOf('Edge/') > 0) { 36 | createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); 37 | } 38 | createElem(doc, tag, 'search.js'); 39 | 40 | $.get(pathtoroot + "module-search-index.zip") 41 | .done(function() { 42 | JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { 43 | var zip = new JSZip(data); 44 | zip.load(data); 45 | moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); 46 | }); 47 | }); 48 | $.get(pathtoroot + "package-search-index.zip") 49 | .done(function() { 50 | JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { 51 | var zip = new JSZip(data); 52 | zip.load(data); 53 | packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); 54 | }); 55 | }); 56 | $.get(pathtoroot + "type-search-index.zip") 57 | .done(function() { 58 | JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { 59 | var zip = new JSZip(data); 60 | zip.load(data); 61 | typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); 62 | }); 63 | }); 64 | $.get(pathtoroot + "member-search-index.zip") 65 | .done(function() { 66 | JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { 67 | var zip = new JSZip(data); 68 | zip.load(data); 69 | memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); 70 | }); 71 | }); 72 | $.get(pathtoroot + "tag-search-index.zip") 73 | .done(function() { 74 | JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { 75 | var zip = new JSZip(data); 76 | zip.load(data); 77 | tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); 78 | }); 79 | }); 80 | if (!moduleSearchIndex) { 81 | createElem(doc, tag, 'module-search-index.js'); 82 | } 83 | if (!packageSearchIndex) { 84 | createElem(doc, tag, 'package-search-index.js'); 85 | } 86 | if (!typeSearchIndex) { 87 | createElem(doc, tag, 'type-search-index.js'); 88 | } 89 | if (!memberSearchIndex) { 90 | createElem(doc, tag, 'member-search-index.js'); 91 | } 92 | if (!tagSearchIndex) { 93 | createElem(doc, tag, 'tag-search-index.js'); 94 | } 95 | $(window).resize(function() { 96 | $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 97 | }); 98 | } 99 | 100 | function createElem(doc, tag, path) { 101 | var script = doc.createElement(tag); 102 | var scriptElement = doc.getElementsByTagName(tag)[0]; 103 | script.src = pathtoroot + path; 104 | scriptElement.parentNode.insertBefore(script, scriptElement); 105 | } 106 | 107 | function show(type) 108 | { 109 | count = 0; 110 | for (var key in methods) { 111 | var row = document.getElementById(key); 112 | if ((methods[key] & type) !== 0) { 113 | row.style.display = ''; 114 | row.className = (count++ % 2) ? rowColor : altColor; 115 | } 116 | else 117 | row.style.display = 'none'; 118 | } 119 | updateTabs(type); 120 | } 121 | 122 | function showPkgs(type) 123 | { 124 | count = 0; 125 | for (var key in packages) { 126 | var row = document.getElementById(key); 127 | if ((packages[key] & type) !== 0) { 128 | row.style.display = ''; 129 | row.className = (count++ % 2) ? rowColor : altColor; 130 | } 131 | else 132 | row.style.display = 'none'; 133 | } 134 | updatePkgsTabs(type); 135 | } 136 | 137 | function updateTabs(type) 138 | { 139 | for (var value in tabs) { 140 | var sNode = document.getElementById(tabs[value][0]); 141 | var spanNode = sNode.firstChild; 142 | if (value == type) { 143 | sNode.className = activeTableTab; 144 | spanNode.innerHTML = tabs[value][1]; 145 | } 146 | else { 147 | sNode.className = tableTab; 148 | spanNode.innerHTML = "" + tabs[value][1] + ""; 149 | } 150 | } 151 | } 152 | 153 | function updateModuleFrame(pFrame, cFrame) 154 | { 155 | top.packageFrame.location = pFrame; 156 | top.classFrame.location = cFrame; 157 | } 158 | 159 | function updatePkgsTabs(type) 160 | { 161 | for (var value in tabs) { 162 | var sNode = document.getElementById(tabs[value][0]); 163 | var spanNode = sNode.firstChild; 164 | if (value == type) { 165 | sNode.className = activeTableTab; 166 | spanNode.innerHTML = tabs[value][1]; 167 | } 168 | else { 169 | sNode.className = tableTab; 170 | spanNode.innerHTML = "" + tabs[value][1] + ""; 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /documentation/serialized-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
CannotDecodeException
with the specified error message.
11 | *
12 | * @param message the error message which can be retrieved with the getMessage
method
13 | */
14 | public CannotDecodeException(String message) {super(message);}
15 |
16 | /**
17 | * Constructs a new CannotDecodeException
with the specified error message and cause.
18 | *
19 | * @param message the error message which can be retrieved with the getMessage
method
20 | * @param cause the cause (which is saved for later retrieval by the Throwable.getCause() method). (A null value is permitted, and indicates that the cause is nonexistent or unknown.)
21 | */
22 | public CannotDecodeException(String message, Throwable cause) {super(message, cause);}
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/Steganography/Exceptions/CannotEncodeException.java:
--------------------------------------------------------------------------------
1 | package Steganography.Exceptions;
2 |
3 | /**
4 | * The {@code CannotEncodeException} exception is thrown when an error occurs when encoding an image,
5 | * mainly empty data or larger data than capacity.
6 | */
7 | public class CannotEncodeException extends Exception{
8 |
9 | /**
10 | * Constructs a new CannotDecodeException
with the specified error message.
11 | *
12 | * @param message the error message which can be retrieved with the getMessage
method
13 | */
14 | public CannotEncodeException(String message) {super(message);}
15 |
16 | /**
17 | * Constructs a new CannotDecodeException
with the specified error message and cause.
18 | *
19 | * @param message the error message which can be retrieved with the getMessage
method
20 | * @param cause the cause (which is saved for later retrieval by the Throwable.getCause() method). (A null value is permitted, and indicates that the cause is nonexistent or unknown.)
21 | */
22 | public CannotEncodeException(String message, Throwable cause) {super(message, cause);}
23 | }
24 |
--------------------------------------------------------------------------------
/src/Steganography/Exceptions/UnsupportedImageTypeException.java:
--------------------------------------------------------------------------------
1 | package Steganography.Exceptions;
2 |
3 | /**
4 | * The {@code UnsupportedImageTypeException} exception is thrown when the cover image is unsupported by the encoding process.
5 | * e.g. : grayscale images, 16bit images...
6 | */
7 | public class UnsupportedImageTypeException extends Exception{
8 |
9 | /**
10 | * Constructs a new CannotDecodeException
with the specified error message.
11 | *
12 | * @param message the error message which can be retrieved with the getMessage
method
13 | */
14 | public UnsupportedImageTypeException(String message) {super(message);}
15 |
16 | /**
17 | * Constructs a new CannotDecodeException
with the specified error message and cause.
18 | *
19 | * @param message the error message which can be retrieved with the getMessage
method
20 | * @param cause the cause (which is saved for later retrieval by the Throwable.getCause() method). (A null value is permitted, and indicates that the cause is nonexistent or unknown.)
21 | */
22 | public UnsupportedImageTypeException(String message, Throwable cause) {super(message, cause);}
23 | }
24 |
--------------------------------------------------------------------------------
/src/Steganography/Exceptions/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The {@code Steganography.Exceptions} package contains custom exceptions that extend {@link java.lang.Exception}
3 | * and are thrown during the steganography process in {@link Steganography.Logic}.
4 | */
5 | package Steganography.Exceptions;
--------------------------------------------------------------------------------
/src/Steganography/Logic/GifSequenceWriter.java:
--------------------------------------------------------------------------------
1 | // GifSequenceWriter.java
2 | //
3 | // Created by Elliot Kroo on 2009-04-25.
4 | // Modified by Feres Gaaloul on 2018-07.
5 | //
6 | // This work is licensed under the Creative Commons Attribution 3.0 Unported
7 | // License. To view a copy of this license, visit
8 | // http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative
9 | // Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
10 |
11 | package Steganography.Logic;
12 |
13 | import javax.imageio.IIOException;
14 | import javax.imageio.IIOImage;
15 | import javax.imageio.ImageIO;
16 | import javax.imageio.ImageTypeSpecifier;
17 | import javax.imageio.ImageWriteParam;
18 | import javax.imageio.ImageWriter;
19 | import javax.imageio.metadata.IIOMetadata;
20 | import javax.imageio.metadata.IIOMetadataNode;
21 | import javax.imageio.stream.ImageOutputStream;
22 | import java.awt.image.RenderedImage;
23 | import java.io.IOException;
24 | import java.util.Iterator;
25 |
26 | /**
27 | * The {@code GifSequenceWriter} class is used by {@link GifSteganography} class
28 | * to create a GIF89a image based on an array of BufferedImage
and an array of IIOMetadata
.
29 | *
30 | * @author Elliot Kroo (2009-04-25).
31 | * @author Feres Gaaloul (2018-07).
32 | */
33 | class GifSequenceWriter {
34 |
35 | /** Used to write a gif image. */
36 | private ImageWriter gifWriter;
37 | /** Describes how the gif will be written. */
38 | private ImageWriteParam imageWriteParam;
39 |
40 | /**
41 | * Creates a new GifSequenceWriter
42 | *
43 | * @author Elliot Kroo (elliot[at]kroo[dot]net)
44 | * @param outputStream the ImageOutputStream to be written to
45 | * @param imageTypeSpecifier the ImageTypeSpecifier of the image
46 | * @param timeBetweenFramesMS the time between frames in milliseconds
47 | * @param loopContinuously whether the gif should loop repeatedly
48 | * @throws IIOException if no gif ImageWriters are found.
49 | */
50 | public GifSequenceWriter(
51 | ImageOutputStream outputStream,
52 | ImageTypeSpecifier imageTypeSpecifier,
53 | int timeBetweenFramesMS,
54 | boolean loopContinuously) throws IOException {
55 | // my method to create a writer
56 | gifWriter = getWriter();
57 | imageWriteParam = gifWriter.getDefaultWriteParam();
58 |
59 | IIOMetadata imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier,
60 | imageWriteParam);
61 |
62 | String metaFormatName = imageMetaData.getNativeMetadataFormatName();
63 |
64 | IIOMetadataNode root = (IIOMetadataNode)
65 | imageMetaData.getAsTree(metaFormatName);
66 |
67 | IIOMetadataNode graphicsControlExtensionNode = Metadata.getNode(
68 | root,
69 | "GraphicControlExtension");
70 |
71 | graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
72 | graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
73 | graphicsControlExtensionNode.setAttribute(
74 | "transparentColorFlag",
75 | "FALSE");
76 | graphicsControlExtensionNode.setAttribute(
77 | "delayTime",
78 | Integer.toString(timeBetweenFramesMS / 10));
79 | graphicsControlExtensionNode.setAttribute(
80 | "transparentColorIndex",
81 | "0");
82 |
83 | IIOMetadataNode commentsNode = Metadata.getNode(root, "CommentExtensions");
84 | commentsNode.setAttribute("CommentExtension", "Created by MAH");
85 |
86 | IIOMetadataNode appEntensionsNode = Metadata.getNode(
87 | root,
88 | "ApplicationExtensions");
89 | IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
90 |
91 | child.setAttribute("applicationID", "NETSCAPE");
92 | child.setAttribute("authenticationCode", "2.0");
93 | int loop = loopContinuously ? 0 : 1;
94 |
95 | child.setUserObject(new byte[]{0x1, (byte) (loop & 0xFF),
96 | (byte) ((loop >> 8) & 0xFF)});
97 | appEntensionsNode.appendChild(child);
98 |
99 | imageMetaData.setFromTree(metaFormatName, root);
100 |
101 | gifWriter.setOutput(outputStream);
102 |
103 | gifWriter.prepareWriteSequence(null);
104 | }
105 |
106 | /**
107 | * Returns the first available GIF ImageWriter using
108 | * ImageIO.getImageWritersBySuffix("gif").
109 | *
110 | * @return a GIF ImageWriter object.
111 | * @throws IIOException if no GIF image writers are returned.
112 | */
113 | private static ImageWriter getWriter() throws IIOException {
114 | IteratorIIOMetadata
that contains the metadatas of each frame of a given gif image.
38 | *
39 | * @param gif image to extract metadata from
40 | * @return an array of metadatas for each frame of the gif image.
41 | * @throws IOException if an error occurs while handling the gif image file.
42 | */
43 | public static IIOMetadata[] getMetadatas(File gif) throws IOException{
44 | ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();
45 | ImageInputStream input = ImageIO.createImageInputStream(gif);
46 | reader.setInput(input);
47 | int count = reader.getNumImages(true);
48 | IIOMetadata[] metadatas = new IIOMetadata[count];
49 | for(int index = 0; index < count; index++)
50 | metadatas[index] = reader.getImageMetadata(index);
51 | return metadatas;
52 | }
53 |
54 | /**
55 | * Returns the original delay of the gif image (delay of the first frame).
56 | *
57 | * @param gif image to extract the initial delay from (in milliseconds)
58 | * @return the delay of the first frame of the given gif in milliseconds.
59 | * @throws IOException if an error occurs while handling the gif image file.
60 | */
61 | public static int getDelayMS(File gif) throws IOException{
62 | ImageReader gif_img = ImageIO.getImageReadersBySuffix("gif").next();
63 | ImageInputStream input = ImageIO.createImageInputStream(gif);
64 | gif_img.setInput(input);
65 | IIOMetadata imageMetaData = gif_img.getImageMetadata(0);
66 | String metaFormatName = imageMetaData.getNativeMetadataFormatName();
67 | IIOMetadataNode root = (IIOMetadataNode)imageMetaData.getAsTree(metaFormatName);
68 | IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
69 | return Integer.parseInt(graphicsControlExtensionNode.getAttribute("delayTime"));
70 | }
71 |
72 | /**
73 | * Returns an existing child node, or creates and returns a new child node (if
74 | * the requested node does not exist).
75 | *
76 | * @param rootNode the IIOMetadataNode
to search for the child node
77 | * @param nodeName the name of the child node
78 | * @return the child node, if found or a new node created with the given name.
79 | */
80 | public static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName) {
81 | int nNodes = rootNode.getLength();
82 | for (int i = 0; i < nNodes; i++)
83 | if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0)
84 | return((IIOMetadataNode) rootNode.item(i));
85 | IIOMetadataNode node = new IIOMetadataNode(nodeName);
86 | rootNode.appendChild(node);
87 | return(node);
88 | }
89 |
90 | }
--------------------------------------------------------------------------------
/src/Steganography/Logic/Utils.java:
--------------------------------------------------------------------------------
1 | package Steganography.Logic;
2 |
3 | import Steganography.Modals.AlertBox;
4 |
5 | import javax.imageio.ImageIO;
6 | import java.awt.image.BufferedImage;
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.util.List;
10 |
11 | /**
12 | * The final {@code Utils} class contains methods used by other classes in the project to reduce redundancy.
13 | */
14 | public final class Utils {
15 |
16 | /**
17 | * Returns the extension of a given file.
18 | *
19 | * @param file file to extract extension from
20 | * @return the extension of the given file.
21 | */
22 | public static String getFileExtension(File file) {
23 | String filename = file.getName();
24 | return filename.substring(filename.lastIndexOf(".")+1);
25 | }
26 |
27 | /**
28 | * Converts a list of bytes to a byte array with the appropriate size.
29 | *
30 | * @param in list of bytes to convert
31 | * @return the byte array after conversion.
32 | */
33 | public static byte[] toByteArray(ListDeflator
is used to compress data and Inflator
to decompress data.
20 | */
21 | public class ZLibCompression {
22 |
23 | /** Size of the buffer used to compress a file by chucks. */
24 | private static final int BUF_SIZE = 256;
25 |
26 | /**
27 | * Compresses a given file into another file using Deflator
from the ZLib java library.
28 | *
29 | * @param raw file to compress
30 | * @param compressed file to which compressed data will be written
31 | */
32 | public static void compress(File raw, File compressed){
33 | try{
34 | InputStream is = new FileInputStream(raw);
35 | OutputStream os = new DeflaterOutputStream(new FileOutputStream(compressed));
36 | copy(is, os);
37 |
38 | }catch (IOException e) {
39 | e.printStackTrace();
40 | AlertBox.error("Error while compressing", e.getMessage());
41 | }
42 | }
43 |
44 | /**
45 | * Compresses a given byte array into another file using Deflator
from the ZLib java library.
46 | *
47 | * @param raw byte array to compress
48 | * @return a byte array with the compressed data.
49 | */
50 | public static byte[] compress(byte [] raw){
51 | InputStream is = new ByteArrayInputStream(raw);
52 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
53 | OutputStream os = new DeflaterOutputStream(baos);
54 | try{
55 | copy(is, os);
56 | return baos.toByteArray();
57 |
58 | }catch (IOException e){
59 | e.printStackTrace();
60 | AlertBox.error("Error while compressing", e.getMessage());
61 | return null;
62 | }
63 | }
64 |
65 | /**
66 | * Decompresses a given file that was compressed by {@link #compress(File, File)} using Inflator
.
67 | *
68 | * @param compressed file to be decompressed
69 | * @param raw file to which decompressed data will be written
70 | */
71 | public static void decompress(File compressed, File raw){
72 | try{
73 | InputStream is = new InflaterInputStream(new FileInputStream(compressed));
74 | OutputStream os = new FileOutputStream(raw);
75 | copy(is, os);
76 | }catch (IOException e){
77 | e.printStackTrace();
78 | AlertBox.error("Error while decompressing", e.getMessage());
79 | }
80 | }
81 |
82 | /**
83 | * Decompresses a given byte array that was compressed by {@link #compress(byte[])} using Inflator
.
84 | *
85 | * @param compressed byte array to be decrypted
86 | * @return a byte array with the decompressed data.
87 | */
88 | public static byte[] decompress(byte[] compressed){
89 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
90 | OutputStream os = baos;
91 | InputStream is = new InflaterInputStream(new ByteArrayInputStream(compressed));
92 | try {
93 | copy(is, os);
94 | return baos.toByteArray();
95 | }catch (IOException e){
96 | e.printStackTrace();
97 | AlertBox.error("Error while decompressing", e.getMessage());
98 | return null;
99 | }
100 | }
101 |
102 | /**
103 | * Copies an InputStream
to an OutputStream
in chucks using a buffer
104 | *
105 | * @param is InputStream
(source of data)
106 | * @param os OutputStream
(destination of data)
107 | * @throws IOException if an error occurs when reading from InputStream
or writing to OutputStream
.
108 | */
109 | private static void copy(InputStream is, OutputStream os) throws IOException{
110 | byte[] buffer = new byte[BUF_SIZE];
111 | int length;
112 | while ((length = is.read(buffer)) > 0)
113 | os.write(buffer, 0, length);
114 | is.close();
115 | os.close();
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/src/Steganography/Logic/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The {@code Steganography.Logic} package contains all the classes used to handle the
3 | * steganography, encryption and compression processes (and more...) in the {@link Steganography} package.
4 | */
5 | package Steganography.Logic;
--------------------------------------------------------------------------------
/src/Steganography/Main.java:
--------------------------------------------------------------------------------
1 | package Steganography;
2 |
3 | import javafx.application.Application;
4 | import javafx.fxml.FXMLLoader;
5 | import javafx.scene.Parent;
6 | import javafx.scene.Scene;
7 | import javafx.stage.Stage;
8 | import javafx.scene.image.Image;
9 |
10 | import java.io.IOException;
11 |
12 | /**
13 | * Entry point of the StegIt app. The JavaFX
runtime handles the launch of the application.
14 | */
15 | public class Main extends Application {
16 |
17 | /**
18 | * Application entry point.
19 | * Generates the main StegIt window from the layout.fxml file and displays it.
20 | *
21 | * @param primaryStage application main stage
22 | * @throws IOException if an error occurs while loading resources.
23 | */
24 | @Override
25 | public void start(Stage primaryStage) throws IOException{
26 | Parent root = FXMLLoader.load(getClass().getResource("Resources/layout.fxml"));
27 | Image icon = new Image(Controller.class.getResource("Resources/logo.png").toExternalForm(), false);
28 | Scene scene = new Scene(root);
29 | primaryStage.setScene(scene);
30 | primaryStage.setTitle("StegIt");
31 | primaryStage.setMinWidth(900);
32 | primaryStage.setMinHeight(600);
33 | primaryStage.getIcons().add(icon);
34 | primaryStage.show();
35 | }
36 |
37 | /**
38 | * The main() method is ignored in correctly deployed JavaFX
application.
39 | * main() serves only as fallback in case the application can not be launched
40 | * through deployment artifacts, e.g., in IDEs with limited JavaFX
support.
41 | *
42 | * @param args the command line arguments
43 | */
44 | public static void main(String[] args) {
45 | launch(args);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/Steganography/Modals/AboutPage.java:
--------------------------------------------------------------------------------
1 | package Steganography.Modals;
2 |
3 | import javafx.geometry.Insets;
4 | import javafx.geometry.Pos;
5 | import javafx.scene.Scene;
6 | import javafx.scene.control.Label;
7 | import javafx.scene.image.Image;
8 | import javafx.scene.image.ImageView;
9 | import javafx.scene.layout.BorderPane;
10 | import javafx.scene.layout.VBox;
11 | import javafx.scene.text.Font;
12 | import javafx.stage.Modality;
13 | import javafx.stage.Stage;
14 |
15 | /**
16 | * The {@code AboutPage} class creates a JavaFX
application modal to display information about the StegIt app.
17 | */
18 | public class AboutPage {
19 |
20 | /**
21 | * Displays the AboutPage modal window.
22 | */
23 | public static void display(){
24 | Stage window = new Stage();
25 | window.initModality(Modality.APPLICATION_MODAL);
26 |
27 | ImageView imgView = new ImageView(new Image(("Steganography/Resources/logo.png"), 150, 150, true, true));
28 | Label appName = new Label("StegIt");
29 | appName.setFont(new Font(20));
30 | VBox logo = new VBox();
31 | logo.setAlignment(Pos.CENTER);
32 | logo.setSpacing(6);
33 | logo.getChildren().addAll(imgView, appName);
34 |
35 | Label appCreators = new Label("Made by : Feres Gaaloul, Ilyes Hamrouni");
36 | appCreators.setFont(new Font(15));
37 | Label appDescription = new Label("The Ultimate Image Steganography App with Password Encryption.\n It Works on gifs too!");
38 | appDescription.setFont(new Font(12));
39 | appDescription.setAlignment(Pos.CENTER);
40 | Label appMoreInfo = new Label("ENSI Summer Project 2018");
41 | Label appVersion = new Label("Version 1.0.1");
42 | appVersion.setFont(new Font(10));
43 | Label appCopyright = new Label("Copyright © Feres Gaaloul, Ilyes Hamrouni 2018");
44 | appCopyright.setFont(new Font(10));
45 |
46 | VBox mainInfo = new VBox(6);
47 | mainInfo.setAlignment(Pos.CENTER);
48 | mainInfo.getChildren().addAll(appName, appCreators, appDescription, appMoreInfo);
49 |
50 | VBox secondaryInfo = new VBox(4);
51 | secondaryInfo.setAlignment(Pos.CENTER);
52 | secondaryInfo.getChildren().addAll(appVersion, appCopyright);
53 |
54 | BorderPane layout = new BorderPane();
55 | layout.setPadding(new Insets(10));
56 | layout.setTop(logo);
57 | layout.setCenter(mainInfo);
58 | layout.setBottom(secondaryInfo);
59 |
60 | Scene scene = new Scene(layout, 400, 400);
61 | window.setScene(scene);
62 | window.setTitle("About StegIt");
63 | window.showAndWait();
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/Steganography/Modals/AlertBox.java:
--------------------------------------------------------------------------------
1 | package Steganography.Modals;
2 |
3 | import javafx.scene.control.Alert;
4 | import javafx.scene.control.ButtonBar;
5 | import javafx.scene.control.ButtonType;
6 | import javafx.scene.control.TextArea;
7 | import javafx.scene.layout.GridPane;
8 | import javafx.scene.layout.Priority;
9 |
10 | import java.awt.Desktop;
11 | import java.io.File;
12 | import java.io.IOException;
13 | import java.util.Optional;
14 |
15 | /**
16 | * The {@code AlertBox} class is uses the JavaFX Alert
modal to display either caught error messages
17 | * or various information about a successful steganography process.
18 | */
19 | public class AlertBox {
20 |
21 | /**
22 | * Displays an error Alert box to display a caught error during the steganographic process.
23 | *
24 | * @param header error header
25 | * @param content general information about the error (usually from the getMessage
method from the Java Exception
class)
26 | */
27 | public static void error(String header, String content) {
28 | Alert alert = new Alert(Alert.AlertType.ERROR);
29 | alert.setTitle("Error");
30 | alert.setHeaderText(header);
31 | alert.setContentText(content);
32 | alert.showAndWait();
33 | }
34 |
35 | /**
36 | * Displays a success prompt after embeding data into an image or extracting a document or an image inside an image.
37 | *
38 | * @param header information header
39 | * @param content success message
40 | * @param file image or document to display
41 | * @throws IOException if an error occurs when opening the file.
42 | */
43 | public static void information(String header, String content, File file) throws IOException{
44 | Alert alert = new Alert(Alert.AlertType.INFORMATION);
45 | alert.setTitle("Information");
46 | alert.setHeaderText(header);
47 | alert.setContentText(content);
48 |
49 | ButtonType viewButton = new ButtonType("View");
50 | ButtonType cancelButton = new ButtonType("Close", ButtonBar.ButtonData.CANCEL_CLOSE);
51 | alert.getButtonTypes().setAll(viewButton, cancelButton);
52 |
53 | OptionalJavaFX
application modals
3 | * used by the {@link Steganography} package to form the application's graphical user interface.
4 | */
5 |
6 | package Steganography.Modals;
--------------------------------------------------------------------------------
/src/Steganography/Resources/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/src/Steganography/Resources/logo.png
--------------------------------------------------------------------------------
/src/Steganography/Resources/modena_dark.css:
--------------------------------------------------------------------------------
1 | /* base colors */
2 | .root {
3 | -fx-base: rgb(38, 38, 38);
4 | -fx-background: rgb(38, 38, 38);
5 |
6 | /* make controls (buttons, thumb, etc.) slightly lighter */
7 | -fx-color: derive(-fx-base, 10%);
8 |
9 | /* text fields and table rows background */
10 | -fx-control-inner-background: rgb(28, 28, 28);
11 | /* version of -fx-control-inner-background for alternative rows */
12 | -fx-control-inner-background-alt: derive(-fx-control-inner-background, 2.5%);
13 |
14 | /* text colors depending on background's brightness */
15 | -fx-light-text-color: rgb(232, 232, 232);
16 | -fx-mid-text-color: rgb(58, 58, 58);
17 | -fx-dark-text-color: rgb(28, 28, 28);
18 |
19 | /* A bright blue for highlighting/accenting objects. For example: selected
20 | * text; selected items in menus, lists, trees, and tables; progress bars */
21 | -fx-accent: rgb(0, 80, 100);
22 |
23 | /* color of non-focused yet selected elements */
24 | -fx-selection-bar-non-focused: rgb(58, 58, 58);
25 | }
26 |
27 | /* Fix derived prompt color for text fields */
28 | .text-input {
29 | -fx-prompt-text-fill: derive(-fx-control-inner-background, +50%);
30 | }
31 |
32 | /* Keep prompt invisible when focused (above color fix overrides it) */
33 | .text-input:focused {
34 | -fx-prompt-text-fill: transparent;
35 | }
36 |
37 | /* Fix scroll bar buttons arrows colors */
38 | .scroll-bar > .increment-button > .increment-arrow,
39 | .scroll-bar > .decrement-button > .decrement-arrow {
40 | -fx-background-color: -fx-mark-highlight-color, rgb(220, 220, 220);
41 | }
42 |
43 | .scroll-bar > .increment-button:hover > .increment-arrow,
44 | .scroll-bar > .decrement-button:hover > .decrement-arrow {
45 | -fx-background-color: -fx-mark-highlight-color, rgb(240, 240, 240);
46 | }
47 |
48 | .scroll-bar > .increment-button:pressed > .increment-arrow,
49 | .scroll-bar > .decrement-button:pressed > .decrement-arrow {
50 | -fx-background-color: -fx-mark-highlight-color, rgb(255, 255, 255);
51 | }
--------------------------------------------------------------------------------
/src/Steganography/Resources/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The {@code Steganography.Ressources} package contains various resource files used by JavaFX
3 | * to form the application's graphical user interface (layout, stylesheet, icon)
4 | */
5 |
6 | package Steganography.Resources;
--------------------------------------------------------------------------------
/src/Steganography/Resources/stylesheet.css:
--------------------------------------------------------------------------------
1 | #secretDocumentContent{
2 | -fx-background-color: transparent;
3 | }
4 |
5 | #secretDocumentContent .list-cell:even {
6 | -fx-background-color: white;
7 | -fx-text-fill: black;
8 | }
9 | #secretDocumentContent .list-cell:odd {
10 | -fx-background-color: white;
11 | -fx-text-fill: black;
12 | }
13 |
14 | .background{
15 | -fx-background-color: #393939;
16 | }
--------------------------------------------------------------------------------
/src/Steganography/Types/DataFormat.java:
--------------------------------------------------------------------------------
1 | package Steganography.Types;
2 |
3 | /**
4 | * Format of the data that is hidden inside the steganographic image.
5 | */
6 | public enum DataFormat {
7 | /** Embedded message byte array in image. */
8 | MESSAGE,
9 | /** Embedded file document in image. */
10 | DOCUMENT,
11 | /** Embedded image in image.
12 | * @see Steganography.Logic.ImageInImageSteganography */
13 | IMAGE}
14 |
--------------------------------------------------------------------------------
/src/Steganography/Types/PasswordType.java:
--------------------------------------------------------------------------------
1 | package Steganography.Types;
2 |
3 | /**
4 | * Sets the behaviour of the PasswordPrompt based on the type of the operation.
5 | *
6 | * @see Steganography.Modals.PasswordPrompt
7 | */
8 | public enum PasswordType {
9 | /** Use the Encryption mode (password validation and confirmation box). */
10 | ENCRYPT,
11 | /** Use the Decryption mode. */
12 | DECRYPT}
13 |
--------------------------------------------------------------------------------
/src/Steganography/Types/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The {@code Steganography.Types} package contains special data types or enum
s used in the {@link Steganography} package.
3 | */
4 | package Steganography.Types;
--------------------------------------------------------------------------------
/src/Steganography/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The {@code Steganography} package contains the main application launcher and controller and the various packages used by the StegIt application.
3 | *
4 | * @see Steganography.Logic
5 | * @see Steganography.Modals
6 | * @see Steganography.Types
7 | * @see Steganography.Resources
8 | */
9 | package Steganography;
--------------------------------------------------------------------------------
/testFiles/ENSI.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/ENSI.jpg
--------------------------------------------------------------------------------
/testFiles/cat.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/cat.gif
--------------------------------------------------------------------------------
/testFiles/colors.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/colors.gif
--------------------------------------------------------------------------------
/testFiles/cute.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/cute.gif
--------------------------------------------------------------------------------
/testFiles/fuck.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/fuck.gif
--------------------------------------------------------------------------------
/testFiles/gatsby.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/gatsby.jpg
--------------------------------------------------------------------------------
/testFiles/giphy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/giphy.gif
--------------------------------------------------------------------------------
/testFiles/hello.txt:
--------------------------------------------------------------------------------
1 | hello, world!
2 | héééllo's world!!!ààà?
3 |
--------------------------------------------------------------------------------
/testFiles/human.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/human.gif
--------------------------------------------------------------------------------
/testFiles/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/image.png
--------------------------------------------------------------------------------
/testFiles/image2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/image2.png
--------------------------------------------------------------------------------
/testFiles/leo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/leo.gif
--------------------------------------------------------------------------------
/testFiles/lol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/lol.png
--------------------------------------------------------------------------------
/testFiles/merc.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/merc.bmp
--------------------------------------------------------------------------------
/testFiles/ohno.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/feresg/java-steganography/1884a4f936296cd0e1ce94163321120f59135eb4/testFiles/ohno.gif
--------------------------------------------------------------------------------
/testFiles/test.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf400
2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 ArialMT;}
3 | {\colortbl;\red255\green255\blue255;\red0\green0\blue255;\red243\green235\blue10;\red255\green255\blue51;
4 | \red74\green0\blue230;\red255\green255\blue255;\red251\green2\blue7;\red0\green0\blue0;\red0\green0\blue255;
5 | \red41\green0\blue130;\red127\green127\blue127;}
6 | {\*\expandedcolortbl;;\cssrgb\c1680\c19835\c100000;\cssrgb\c96264\c92423\c0;\cssrgb\c99946\c98636\c25320;
7 | \cssrgb\c36820\c18688\c92265;\cssrgb\c100000\c100000\c100000;\cssrgb\c100000\c14913\c0;\cssrgb\c0\c0\c0;\cssrgb\c1680\c19835\c100000;
8 | \cssrgb\c21681\c10251\c58230;\cssrgb\c57046\c57047\c57046;}
9 | \paperw11900\paperh16840\margl1440\margr1440\vieww12600\viewh10200\viewkind0
10 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
11 |
12 | \f0\fs36 \cf2 \cb3 TESTING RTF FILES\
13 |
14 | \f1 \cf4 \cb5 DIFFERENT FONTS\
15 |
16 | \fs96 \cf6 \cb7 DIFFERENT SIZES\
17 |
18 | \fs192 \cb8 IS IT WORKING\
19 | ???\
20 | \cf7 \cb9 SO MANY FUCKING COLORS!!!!!!!!\
21 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
22 | \cf7 \cb10 \
23 |
24 | \fs128 \cf11 goodbye now\'85\
25 | \cf7 \cb6 to be continued\'85\'85\'85\cb9 \
26 | }
--------------------------------------------------------------------------------
/testFiles/testar.txt:
--------------------------------------------------------------------------------
1 | تونس دولة حرة مستقلة الإسلام دينها والعربية لغتها والجمهورية نظامها. (لا يجوز تعديل هذا الفصل)
2 |
3 | أداء الضريبة وتحمل التكاليف العامة واجب وفق نظام عادل ومنصف.
4 | تضع الدولة الآليات الكفيلة بضمان استخلاص الضريبة و منع الفساد و كل ما من شأنه رهن الموارد و السيادة الوطنية ومقاومة التهرّب والغش الجبائيين. و تحرص الدولة علي حسن التصرف في المال العمومي، وتتخذ التدابير اللازمة لصرفه حسب أولويات الاقتصاد الوطني.
5 |
6 | على كل من يتولى رئاسة الجمهورية أو رئاسة الحكومة أو عضويتها أو عضوية مجلس نواب الشعب أو عضوية الهيئات الدستورية المستقلة أو أي وظيفة عليا أن يصرح بمكاسبه وفق ما يضبطه القانون.
7 |
8 | تسعى الدولة الى الاستغلال الرشيد للثروات الوطنية والى تحقيق العدالة الاجتماعية والتنمية المستدامة والتوازن بين الجهات استنادا الى مؤشرات التنمية واعتمادا على مبدأ التمييز الإيجابي .
9 |
10 | تلتزم الدولة بدعم اللامركزية واعتمادها بكامل التراب الوطني في إطار وحدة الدولة.
11 |
12 | الإدارة العمومية في خدمة المواطن والصالح العام. تنظم وتعمل وفق مبادئ الحياد والمساواة واستمرارية المرفق العام، ووفق قواعد الشفافية والنزاهة والنجاعة والمساءلة.
13 |
14 | تضمن الدولة حياد المؤسسات التربوية عن التوظيف الحزبي.
15 |
16 | تحتكر الدولة إنشاء القوات المسلحة، وقوات الأمن الوطني، ويكون ذلك بمقتضى القانون ولخدمة الصالح العام.
17 |
18 | الجيش الوطني جيش جمهوري وهو قوة عسكرية مسلحة قائمة على الانضباط، مؤلفة ومنظمة هيكليا طبق القانون، ويضطلع بواجب الدفاع عن الوطن واستقلاله ووحدة ترابه، وهو ملزم بالحياد التام. ويدعم الجيش الوطني السلطات المدنية وفق ما يضبطه القانون.
19 |
20 | الأمن الوطني أمن جمهوري قواته مكلفة بحفظ الأمن، والنظام العام، وحماية الأفراد والمؤسسات والممتلكات، وإنفاذ القانون، في كنف احترام الحريات وفي إطار الحياد التامّ.
21 |
22 | تونس دولة مدنية تقوم على إرادة الشعب وعلوية القانون .(لا يجوز تعديل هذا الفصل)
23 |
24 | الشعب هو صاحب السيادة ومصدر السلطات ويمارسها بواسطة ممثليه المنتخبين أو عبر الاستفتاء.
25 |
26 | علم الجمهورية التونسية أحمر يتوسطه قرص أبيض به نجم أحمر ذو خمسة أشعة يحيط به هلال أحمر حسبما يضبطه القانون. النشيد الرسمي للجمهورية هو "حماة الحمى" ويضبط بقانون. شعار الجمهورية التونسية هو "حرية وكرامة وعدالة ونظام".
27 |
28 | الجمهورية التونسية جزء من المغرب العربي ،تعمل على تحقيق وحدته وتتخذ كافة التدابير لتجسيمها.
29 |
30 | الدّولة راعية للدّين، كافلة لحريّة المعتقد والضّمير وممارسة الشّعائر الدّينيّة، ضامنة لحياد المساجد ودور العبادة عن التّوظيف الحزبي.
31 |
32 | تلتزم الدّولة بنشر قيم الاعتدال والتّسامح وبحماية المقدّسات ومنع النّيل منها، كما تلتزم بمنع دعوات التّكفير والتّحريض على الكراهية والعنف وبالتّصدّي لها.
33 |
34 | الأسرة هي الخلية الأساسية للمجتمع ،وعلى الدولة حمايتها.
35 |
36 | الشباب قوة فاعلة في بناء الوطن.
37 | تحرص الدولة على توفير الظروف الكفيلة بتنمية قدرات الشباب وتفعيل طاقاته وتعمل على تحمله المسؤولية وعلى توسيع إسهامه في التنمية الاجتماعية والاقتصادية والثقافية والسياسية.
38 |
39 | ينص الفصل على أن الحفاظ على وحدة الوطن و الدفاع عن حرمته واجب مقدس على كل المواطنين و على أن الخدمة الوطنية واجب حسب الصيغ و الشروط التى يضبطها القانون.
40 |
--------------------------------------------------------------------------------