Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# imgconceal: steganography on JPEG, PNG and WebP images

*imgconceal* is a tool for image steganography, that can hide files inside JPEG, PNG and WebP images. A password an be used for extracting the data later. The image with hidden data looks the same to the human eye as the regular image.
*imgconceal* is a tool for image steganography, that can hide files inside JPEG, PNG and WebP images. A password can be used for extracting the data later. The image with hidden data looks the same to the human eye as the regular image.

**Downloads:**
* [imgconceal for Windows](https://github.com/tbpaolini/imgconceal/releases/download/v1.0.4/imgconceal.exe) (2.60 MB)
Expand Down
18 changes: 9 additions & 9 deletions src/imc_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ static PassBuff *imc_cli_password_input(bool confirm)
}

// Convert an already parsed password string from the system's locale to UTF-8
// 'from_argv' sould be set to 'true' if the string was parsed from the command line options (char *argv[]),
// 'from_argv' should be set to 'true' if the string was parsed from the command line options (char *argv[]),
// otherwise its should be 'false' (that is, read from stdin).
static inline void __password_normalize(PassBuff *password, bool from_argv)
{
Expand Down Expand Up @@ -266,7 +266,7 @@ static inline void __password_normalize(PassBuff *password, bool from_argv)
iconv_t u8_conv = iconv_open("UTF-8", "");
if (!u8_conv) return;

char *const in_text = password->buffer; // Input text in the system's enconding
char *const in_text = password->buffer; // Input text in the system's encoding
size_t in_text_left = password->length; // Amount of bytes of the input remaining to be converted

const size_t out_size = in_text_left * 4; // Size of the output buffer (UTF-8 characters can use up to 4 bytes each)
Expand All @@ -275,7 +275,7 @@ static inline void __password_normalize(PassBuff *password, bool from_argv)
sodium_memzero(out_text, sizeof(out_text));
size_t out_text_left = out_size; // Amount of bytes left in the buffer

// Pointers to the inut and output buffers
// Pointers to the input and output buffers
char *in_text_ptr = in_text; // Current position on the input
char *out_text_ptr = &out_text[0]; // Current position on the output

Expand Down Expand Up @@ -481,7 +481,7 @@ static inline void __execute_options(struct argp_state *state, void *options)
}
else // (mode == EXTRACT) || (mode == CHECK)
{
opt->password = imc_cli_password_input(false); // Input the passowrd once
opt->password = imc_cli_password_input(false); // Input the password once
}
}

Expand Down Expand Up @@ -556,7 +556,7 @@ static inline void __execute_options(struct argp_state *state, void *options)
argp_failure(state, EXIT_FAILURE, 0,
"FAIL: Image '%s' contains no hidden data or the password is incorrect.\n"\
"In order to append files to the image, you have to use the same password as the previously files hidden there.\n"\
"If you want to overwite the existing hidden files (if any), please run the program without the '--append' option.",
"If you want to overwrite the existing hidden files (if any), please run the program without the '--append' option.",
basename(steg_path));
}
}
Expand Down Expand Up @@ -597,7 +597,7 @@ static inline void __execute_options(struct argp_state *state, void *options)

case IMC_ERR_FILE_TOO_BIG:
char size_left[256];
__filesize_to_string((steg_image->carrier_lenght - steg_image->carrier_pos) / 8, size_left, sizeof(size_left));
__filesize_to_string((steg_image->carrier_length - steg_image->carrier_pos) / 8, size_left, sizeof(size_left));
fprintf(
stderr, "FAIL: no enough space in '%s' to hide '%s' (free space: %s).\n",
basename(opt->input), basename(node->data), size_left
Expand All @@ -609,7 +609,7 @@ static inline void __execute_options(struct argp_state *state, void *options)
break;

default:
argp_failure(state, EXIT_FAILURE, 0, "unknown error when hidding data. (%d)", hide_status);
argp_failure(state, EXIT_FAILURE, 0, "unknown error when hiding data. (%d)", hide_status);
break;
}

Expand Down Expand Up @@ -741,7 +741,7 @@ static inline void __execute_options(struct argp_state *state, void *options)
if (mode == CHECK)
{
char str_buffer[256];
__filesize_to_string(steg_image->carrier_lenght / 8, str_buffer, sizeof(str_buffer));
__filesize_to_string(steg_image->carrier_length / 8, str_buffer, sizeof(str_buffer));
printf(
"Image '%s' contains no hidden data or the password is incorrect.\n"
"This image can hide approximately %s "
Expand Down Expand Up @@ -805,7 +805,7 @@ static inline void __execute_options(struct argp_state *state, void *options)
if (mode == CHECK && has_file)
{
char str_buffer[256];
__filesize_to_string((steg_image->carrier_lenght - steg_image->carrier_pos) / 8, str_buffer, sizeof(str_buffer));
__filesize_to_string((steg_image->carrier_length - steg_image->carrier_pos) / 8, str_buffer, sizeof(str_buffer));
printf(
"\nThe cover image '%s' can hide approximately more %s "
"(after compression of hidden data).\n",
Expand Down
2 changes: 1 addition & 1 deletion src/imc_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static PassBuff *__alloc_passbuff();
static PassBuff *imc_cli_password_input(bool confirm);

// Convert an already parsed password string from the system's locale to UTF-8
// 'from_argv' sould be set to 'true' if the string was parsed from the command line options (char *argv[]),
// 'from_argv' should be set to 'true' if the string was parsed from the command line options (char *argv[]),
// otherwise its should be 'false' (that is, read from stdin).
static inline void __password_normalize(PassBuff *password, bool from_argv);

Expand Down
4 changes: 2 additions & 2 deletions src/imc_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ int imc_crypto_context_create(const PassBuff *password, CryptoContext **out)
prng_init(&context->shishua_state, prng_seed);
prng_gen(&context->shishua_state, context->prng_buffer.buf, IMC_PRNG_BUFFER);

// Release the unecessary memory and store the output
// Release the unnecessary memory and store the output
sodium_munlock(prng_seed, sizeof(prng_seed));
sodium_munlock(output, sizeof(output));
*out = context;
Expand Down Expand Up @@ -169,7 +169,7 @@ int imc_crypto_encrypt(
// Add the bytes needed by libsodium's header
*output_len += crypto_secretstream_xchacha20poly1305_HEADERBYTES;

// Pointers to the adresses where the version and size will be written
// Pointers to the addresses where the version and size will be written
uint32_t *version = (uint32_t *)&output[4];
uint32_t *c_size = (uint32_t *)&output[8];

Expand Down
48 changes: 24 additions & 24 deletions src/imc_image_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ int imc_steg_init(const char *path, const PassBuff *password, CarrierImage **out
imc_crypto_shuffle_ptr(
carrier_img->crypto, // Has the state of the pseudo-random number generator
(uintptr_t *)(&carrier_img->carrier[0]), // Beginning of the array
carrier_img->carrier_lenght, // Amount of elements on the array
carrier_img->carrier_length, // Amount of elements on the array
carrier_img->verbose // Print the progress if on "verbose" mode
);

Expand Down Expand Up @@ -274,7 +274,7 @@ int imc_steg_insert(CarrierImage *carrier_img, const char *file_path)

#ifdef _WIN32
uLongf compress_size_win = zlib_buffer_size;
/* Note: For some reason, on Windows the lenght of the buffer size variable
/* Note: For some reason, on Windows the length of the buffer size variable
is 4 bytes, while on Linux its 8 bytes. Since my code assumes that it is
going to be 8 bytes, then I am creating this additional variable so I do
not pass to the compression function a pointer to a size different than
Expand Down Expand Up @@ -322,7 +322,7 @@ int imc_steg_insert(CarrierImage *carrier_img, const char *file_path)
// Total size of the encrypted stream
const size_t crypto_size = IMC_CRYPTO_OVERHEAD + zlib_buffer_size;

if (crypto_size * 8 > carrier_img->carrier_lenght - carrier_img->carrier_pos)
if (crypto_size * 8 > carrier_img->carrier_length - carrier_img->carrier_pos)
{
// The carrier is not big enough to store the encrypted stream
imc_clear_free(zlib_buffer, zlib_buffer_size);
Expand Down Expand Up @@ -354,7 +354,7 @@ int imc_steg_insert(CarrierImage *carrier_img, const char *file_path)
return IMC_ERR_CRYPTO_FAIL;
}

// Clear and free the buffer of the unencrypted strem
// Clear and free the buffer of the unencrypted stream
imc_clear_free(zlib_buffer, zlib_buffer_size);
if (carrier_img->verbose) printf("Done!\n");

Expand Down Expand Up @@ -395,7 +395,7 @@ int imc_steg_insert(CarrierImage *carrier_img, const char *file_path)
// Returns 'true' if the read could be made (the bytes are stored of the provided buffer).
static bool __read_payload(CarrierImage *carrier_img, size_t num_bytes, uint8_t *out_buffer)
{
if ( (num_bytes * 8) > (carrier_img->carrier_lenght - carrier_img->carrier_pos) )
if ( (num_bytes * 8) > (carrier_img->carrier_length - carrier_img->carrier_pos) )
{
// The amount of data left to be read is bigger than the requested amount
return false;
Expand Down Expand Up @@ -533,7 +533,7 @@ int imc_steg_extract(CarrierImage *carrier_img)

#ifdef _WIN32
uLongf decompress_size_win = decompress_size;
/* Note: For some reason, on Windows the lenght of the buffer size variable
/* Note: For some reason, on Windows the length of the buffer size variable
is 4 bytes, while on Linux its 8 bytes. Since my code assumes that it is
going to be 8 bytes, then I am creating this additional variable so I do
not pass to the decompression function a pointer to a size different than
Expand Down Expand Up @@ -615,7 +615,7 @@ int imc_steg_extract(CarrierImage *carrier_img)
};

// Get the name of the hidden file
char file_name[name_len + 16]; // Extra size added in case it needs to be renamed for avoinding name collision
char file_name[name_len + 16]; // Extra size added in case it needs to be renamed for avoiding name collision
memset(file_name, 0, sizeof(file_name));
memcpy(file_name, file_info->file_name, name_len);

Expand Down Expand Up @@ -705,7 +705,7 @@ void imc_steg_seek_to_end(CarrierImage *carrier_img)

while (true)
{
// Read position after the last successfull check
// Read position after the last successful check
original_pos = carrier_img->carrier_pos;

// Magic bytes of the current data segment
Expand Down Expand Up @@ -807,7 +807,7 @@ void imc_jpeg_carrier_open(CarrierImage *carrier_img)
printf("Reading JPEG image... Done! \n");
}

// Calculate the total amount of DCT coeficients
// Calculate the total amount of DCT coefficients
size_t dct_count = 0;
for (int comp = 0; comp < jpeg_obj->num_components; comp++)
{
Expand Down Expand Up @@ -890,7 +890,7 @@ void imc_jpeg_carrier_open(CarrierImage *carrier_img)
exit(EXIT_FAILURE);
}

// Free the unusued space of the array
// Free the unused space of the array
carrier_bytes = imc_realloc(carrier_bytes, carrier_count * sizeof(uint8_t));

// Store the pointers to each element of the bytes array
Expand All @@ -904,18 +904,18 @@ void imc_jpeg_carrier_open(CarrierImage *carrier_img)
// Store the output
carrier_img->bytes = carrier_bytes; // Array of bytes
carrier_img->carrier = carrier_ptr; // Array of pointers to bytes
carrier_img->carrier_lenght = carrier_count; // Total amount of pointers to bytes
carrier_img->carrier_length = carrier_count; // Total amount of pointers to bytes
carrier_img->object = jpeg_obj; // Image handler

// Store the additional heap allocated memory for the purpose of memory management
carrier_img->heap = imc_malloc(sizeof(void *) * 2);
carrier_img->heap[0] = (void *)jpeg_err;
carrier_img->heap[1] = (void *)jpeg_dct;
carrier_img->heap_lenght = 1;
carrier_img->heap_length = 1;
/* Note:
The lenght above is set to 1, even though it is actually 2, because
The length above is set to 1, even though it is actually 2, because
the memory of '*jpeg_dct' is managed by libjpeg-turbo (instead of my code).
The lenght of 1 prevents my code from attempting to free that memory.
The length of 1 prevents my code from attempting to free that memory.
*/
}

Expand Down Expand Up @@ -1109,7 +1109,7 @@ void imc_png_carrier_open(CarrierImage *carrier_img)

// Store the information about the carrier bytes
carrier_img->carrier = carrier;
carrier_img->carrier_lenght = pos;
carrier_img->carrier_length = pos;
carrier_img->bytes = initial_offset;
}

Expand Down Expand Up @@ -1279,14 +1279,14 @@ void imc_webp_carrier_open(CarrierImage *carrier_img)

// Store the information about the carrier bytes
carrier_img->carrier = carrier;
carrier_img->carrier_lenght = pos;
carrier_img->carrier_length = pos;
carrier_img->bytes = in_buffer;

// Remember the size of the input buffer
carrier_img->heap = imc_malloc(sizeof(void *));
carrier_img->heap[0] = imc_malloc(sizeof(size_t));
*(size_t*)carrier_img->heap[0] = file_size;
carrier_img->heap_lenght = 1;
carrier_img->heap_length = 1;
}

// Change a file path in order to make it unique
Expand Down Expand Up @@ -1366,7 +1366,7 @@ static bool __is_directory(const char *path)
return false;
}

// Copy the "last access" and "last mofified" times from the one file (source) to the other (dest)
// Copy the "last access" and "last modified" times from the one file (source) to the other (dest)
static void __copy_file_times(FILE *source_file, const char *dest_path)
{
#ifdef _WIN32 // Windows systems
Expand Down Expand Up @@ -1404,7 +1404,7 @@ static void __copy_file_times(FILE *source_file, const char *dest_path)

#else // Unix systems

// Get the "last access" and "last mofified" times from the original file
// Get the "last access" and "last modified" times from the original file
const int og_descriptor = fileno(source_file);
struct stat og_stats = {0};
fstat(og_descriptor, &og_stats);
Expand Down Expand Up @@ -1589,7 +1589,7 @@ int imc_jpeg_carrier_save(CarrierImage *carrier_img, const char *save_path)
printf("Writing JPEG image... Done! \n");
}

// Copy the "last access" and "last mofified" times from the original image
// Copy the "last access" and "last modified" times from the original image
__copy_file_times(carrier_img->file, jpeg_path);

return IMC_SUCCESS;
Expand Down Expand Up @@ -1868,7 +1868,7 @@ int imc_png_carrier_save(CarrierImage *carrier_img, const char *save_path)
fclose(png_file);
if (carrier_img->verbose) printf("Writing PNG image... Done! \n");

// Copy the "last access" and "last mofified" times from the original image
// Copy the "last access" and "last modified" times from the original image
__copy_file_times(carrier_img->file, png_path);

return IMC_SUCCESS;
Expand All @@ -1877,7 +1877,7 @@ int imc_png_carrier_save(CarrierImage *carrier_img, const char *save_path)
// Progress monitor when writing a PNG image
static int __webp_write_callback(int percent, const WebPPicture* webp_obj)
{
// Note: libwebp has its own timer for controling the progress update frequency,
// Note: libwebp has its own timer for controlling the progress update frequency,
// so we are not using ours from 'printf_prog()'.
printf("Writing WebP image... %d %%\r", percent);
return true; // Returning 'true' allows the encoding to continue, 'false' would cancel it
Expand Down Expand Up @@ -2029,7 +2029,7 @@ int imc_webp_carrier_save(CarrierImage *carrier_img, const char *save_path)
if (carrier_img->verbose) printf("Writing WebP image... Done! \n");
fclose(webp_file);

// Copy the "last access" and "last mofified" times from the original image
// Copy the "last access" and "last modified" times from the original image
__copy_file_times(carrier_img->file, webp_path);

// Garbage collection
Expand All @@ -2043,7 +2043,7 @@ int imc_webp_carrier_save(CarrierImage *carrier_img, const char *save_path)
// Free the memory of the array of heap pointers in a CarrierImage struct
static void __carrier_heap_free(CarrierImage *carrier_img)
{
for (size_t i = 0; i < carrier_img->heap_lenght; i++)
for (size_t i = 0; i < carrier_img->heap_length; i++)
{
imc_free(carrier_img->heap[i]);
}
Expand Down
10 changes: 5 additions & 5 deletions src/imc_image_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ typedef void (*carrier_close_func)(struct CarrierImage *);
typedef struct CarrierImage
{
// File parameters
FILE *file; // File ponter of the image
FILE *file; // File pointer of the image
void *object; // Pointer to the handler that should be passed to the image processing functions
CryptoContext *crypto; // Secret parameters generated from the password
enum ImageType type; // Format of the image
Expand All @@ -63,8 +63,8 @@ typedef struct CarrierImage
// Manipulation of the file's carrier
carrier_bytes_t bytes; // Carrier bytes (same order as on the image)
carrier_bytes_t *carrier; // Array of pointers to the carrier bytes of the image (array order is shuffled using the password)
size_t carrier_lenght; // Amount of carrier bytes
size_t carrier_pos; // Current writting position on the 'carrier' array
size_t carrier_length; // Amount of carrier bytes
size_t carrier_pos; // Current writing position on the 'carrier' array
carrier_open_func open; // Find the carrier bytes
carrier_save_func save; // Hide data in the carrier
carrier_close_func close; // Free the memory used for the carrier operation
Expand All @@ -75,7 +75,7 @@ typedef struct CarrierImage

// Memory management
void **heap; // Array of pointers to other heap allocated memory for this image
size_t heap_lenght; // Amount of elements on the 'heap' array
size_t heap_length; // Amount of elements on the 'heap' array
} CarrierImage;

// Store the metadata of the hidden file
Expand Down Expand Up @@ -176,7 +176,7 @@ static bool __resolve_filename_collision(char *path);
// Check if a given path is a directory
static bool __is_directory(const char *path);

// Copy the "last access" and "last mofified" times from the one file (source) to the other (dest)
// Copy the "last access" and "last modified" times from the one file (source) to the other (dest)
static void __copy_file_times(FILE *source_file, const char *dest_path);

// Progress monitor when writing a JPEG image
Expand Down
2 changes: 1 addition & 1 deletion src/imc_includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ some conflicts with the symbols defined by `windows.h` or the standard libraries
#include <webp/encode.h> // libwebp (WebP images - encoding)
#include <webp/mux.h> // libwebp (WebP images - container manipulation)
#include <zlib.h> // data compression
#include "../lib/shishua-sse2.h" // Psueudo-random number generator
#include "../lib/shishua-sse2.h" // Pseudo-random number generator

// First party libraries
#include "globals.h"
Expand Down