Skip to content

DaniilGalahov/StG

Repository files navigation

StG

StG logo

Summary

This repository includes:

  • StG - simple steganography application, allows to encrypt/decrypt and embed/extract data to/from images, utilizing AES encryption and advanced steganography algorithms.
  • StGLib - C++ OpenCV-based implementation of +/-1 LSB steganography algorithm with adaptive embedding and randomized selection.
  • StGBridge - C++/CLI interface library for usage StGLib in C#-based apps.
  • StGABI - C ABI .dll for usage StGLib with any managed language (Python, Java, Rust, Go, whatever you need).

Contents

  1. StG app
  2. StG framework
  3. Project roadmap
  4. Support & donations
  5. Legal notice
  6. Contacts

(back to Contents)

StG app

Purpose

This app provides advanced steganography functions, especially:

  • encrypt data with AES and embed encrypted data into .png image.
  • extract encrypted data from .png image and decrypt it with AES.

For AES ciphering the app is using software from this repository.

In simple words

This app allows to hide data into .png image and then extract it from there utilizing method names steganography.

Principle of this method is in mixing of data-to-hide with data of picture utilizing smart math. Imagine you adding a salt to a water. It dissolves and become invisible, but it is still there. And you can extract it, if you, for example, evaporate water. This is what steganography does with data.

If you salted your water properly (i.e., not too hard), it's very difficult to determine (by eye) that it contains something else. Even more difficult to detect the presence of salt if you are adding it not to a pure water, but to a rich soup with vegetables, meat, spices and so on. Same way steganography hides the data in carrier. If amount of data to hide is not too big, it's extremely difficult to detect that an image carries something else.

Modern special steganalysis systems are able to detect probability of presence of hidden data in an image. Same way we can say "Salty!" if we try the soup. But we can not say why it's salty (because of salt or, for example, because of soy sauce).

To reduce possibility of such detection, StG app uses advanced methods of steganography. In a nutshell, the app analyzes carrier picture, determines zones where data hiding will be less visible, and hides data only there. Additionally, during hiding the app shuffles data in pseudo-random way, making it looks like a noise. Developing analogy with a soup, we each time inventing flavouring additive, perfectly matching natural taste of this specific soup.

Beside this StG provides additional level of protection. Before embedding, it encrypts data with AES encryption system (most advanced encryption standard in the world). This way, even if the attacker will detect the presence of steganographed data, he will not be able to decrypt it - without a password it is just a random noise. There is no methods to decipher AES.

Important notices

  1. Data-to-carrier ratio for typical pictures is about 4%. I.e., picture size of 1Mb can contains roughly 40kb of hidden data.
  2. Best choice for carrier pictures - colorful and natural pictures with enough details. Real photos with cosy interiors or beautiful landscapes will be the best option.
  3. WARNING!!! "Under the hood" StG contains military grade encrypting system. If you forget (or lost) the password, NO ONE will be able to decrypt your information! Brute-force time for deciphering AES-256 (even using quantum computers!) exceeds time of heat death of Universe.

Specifications

  • Carrier format: .png, .jpg, .bmp
  • Available encryption standards: AES-128, AES-192, AES-256
  • Stego format: .png
  • Steganography method: +/-1 LSB, adaptive embedding, randomized selection
  • D/C ratio: 0.039

Download

Latest version of StG app can be downloaded here

User interface

User interface of the app allows to:

  • choose the operation
  • set up data file, carrier image file and stego image file paths and parameters of encrypting/decrypting
  • initialize operation
  • receive feedback from the app

"Embed" tab

User interface - embed

This tab allows to embed data to carrier image.

  • Data file field - displays (and allows to input) path to file with data you want to embed.
  • Encryption mode combo box - displays selected AES mode and allows to select other available (AES-128, AES-192 or AES-256).
  • Encryption password field - allows to input your encryption password (at least 8 symbols, with least one capital letter, one digit and one special symbol). This should not be same as stego password.
  • Carrier image file field - displays (and allows to input) path to file of carrier image into which you want to embed data.
  • Stego password field - allows to input your steganography password (at least 8 symbols, with least one capital letter, one digit and one special symbol). This should not be same as encryption password.
  • Stego image file field - displays (and allows to input) path to file of stego image (which is the result of embedding operation).
  • Embed button - initialize embedding operation. Before embedding, system validates all parameters. If something is wrong, system will output a report in "Status" field in the lower left corner of the window.

If data volume is too big for this carrier, system will report status "StGLib::Embed failed. Carrier stegocapacity insufficient." In this case choose bigger carrier image.

"Extract" tab

User interface - extract

  • Stego image file field - displays (and allows to input) path to file of stego image, which contains encrypted data to extract.
  • Stego password field - allows to input your steganography password (at least 8 symbols, with least one capital letter, one digit and one special symbol).
  • Encryption mode combo box - displays selected AES mode and allows to select other available (AES-128, AES-192 or AES-256).
  • Encryption password field - allows to input your encryption password (at least 8 symbols, with least one capital letter, one digit and one special symbol).
  • Data file field - displays (and allows to input) path to file with data (which is the result of extracting operation).
  • Extract button - initialize extract operation. Before extracting, system validates all parameters. If something is wrong, system will output a report in "Status" field in the lower left corner of the window.

In fields Data file, Carrier image file and Stego image file of both tabs you can type the path to appropriate files by yourself or select it via GUI dialogue through "Browse" button near the end of the field.

Notice: system does not touch any info in source files (read-only access), and does not allow to overwrite destination files.


(back to Contents)

StG Framework

Purpose

This library provides open-source, fully-tested (code coverage by tests ~95%) implementation of advanced steganography with AES encryption for .png image files. Feel free to use it in your own projects (of course, following License terms).

Requirements

  • Windows-based OS (Developed on Win 10)
  • Visual Studio Community 2022 Version 17.14.33 (May 2026)
    • Microsoft.Component.MSBuild
    • Visual C++ 2022 (package "Desktop development with C++" in VS Installer)
      • Microsoft.VisualStudio.Component.VC.Redist.14.Latest
      • Microsoft.VisualStudio.Component.VC.CLI.Support
    • C# Tools 4.14.0 (package in VS Installer)
      • Microsoft.Net.Component.4.8.SDK
      • Microsoft.Net.Component.4.8.TargetingPack
  • OpenCV 4.12.0
  • Rijndael AESLib

IDE/SDK configuration

For installation of all required components you need to open Visual Studio Installer -> Workloads, and install next packages:

  • Desktop development with C++
  • .NET desktop development

After this, you need to open Visual Studio Installer -> Individual components, and there install next components:

  • .NET Framework 4.8 SDK
  • .NET Framework 4.8 targeting pack
  • C++/CLI support for v143 build tools (Latest)

Deployment

  • Deploy OpenCV
    • Download OpenCV 4.12.0.
    • Extract it into C:\opencv.
    • Add the bin directory of your OpenCV installation (e.g., C:\opencv\build\x64\vc16\bin) to your system Path variable.
  • Prepare folder structure
    • Create root folder of the project.
    • Inside this folder, create subfolders AES and STG.
  • Clone Rijndael AESLib repo to AES folder using: git clone https://github.com/DaniilGalahov/Rijndael-AESLib.git
  • Clone this repo to StG folder using: git clone https://github.com/DaniilGalahov/StG.git
  • Open it in Visual Studio
  • Rebuild solution (typically Ctrl+Alt+F7)

Now you are ready to work.

Contents

This repository provides:

  • Static C++ library StGLib, implementing core steganography functional (embedding and extracting with adaptive embedding and randomized selection)
  • C++/CLI interface StGBridge, providing access to StGLib functional from C#-based apps
  • C ABI StGABI, providing access to StGLib functional from any managed language (Java, Python, Rust, TypeScript, you name it)

Connecting to third-party project

Library made to be versalite and easy for usage, so to connect it to other project, you should follow standard library integration procedure.

To use in C++ project:

  • add StGLib and AESLib in list of projects of your solution through Add... -> Existing project....
  • add references to StGLib and AESLib in project References.
  • in your project settings, open C/C++ -> General -> Additional Include Directories, and add there:
    • include directory of StGLib (your StG\StGLib).
    • include directory of Rijndael AESLib (your AES\AESLib).
    • include directory of OpenCV (C:\opencv\build\include).

To use in C# project:

  • add StGBridge in list of projects of your solution through Add... -> Existing project....
  • add reference to StGBridge in your project.

To use with other programming languages, follow the standard library integration procedure for selected language. For example, in Python you can use ctypes library.

Coding

C++

  1. Include std::vector (you will need it for work with library) and library header itself
#include <vector>
#include "StGLib.h"
  1. Define helper functions
std::vector<uint8_t> LoadBytesFromFile(std::string filePath)
{
	//reads data from file (via ifstream or any other way) and converts it into array of bytes
}

std::vector<uint8_t> ToBytes(std::string str)
{
	//converts std::string into array of bytes
}
  1. To embed data
	//load data file as an array of bytes
	std::vector<uint8_t> dataBytes = LoadBytesFromFile(dataFilePath);
	
	//load carrier image file as an array of bytes
	std::vector<uint8_t> carrierImageBytes = LoadBytesFromFile(carrierFilePath);

	//converts password string into array of bytes
	std::vector<uint8_t> passwordBytes = ToBytes(password);

	//prepare array of bytes for stego image
	std::vector<uint8_t> stegoImageBytes;

	//embed data to carrier using password as a salt for embedding
	int result = StGLib::Embed(stegoImageBytes, dataBytes, carrierImageBytes, passwordBytes);

Note: StGLib::Embed() will return -1 in case if carrier has not enough volume for given data.

  1. To extract data
	//load stego image file as an array of bytes
	std::vector<uint8_t> stegoImageBytes = LoadFromFile(stegoFilePath);

	//converts password string into array of bytes
	std::vector<uint8_t> passwordBytes = ToBytes(password);

	//prepare array of bytes for data
	std::vector<uint8_t> dataBytes;

	//extract data from stego image
	StGLib::Extract(dataBytes, stegoImageBytes, passwordBytes);

C#

  1. Use System and StGBridge
using System;
using StGBridge;
  1. To embed data
	//read everything from data file into array of bytes
	Byte[] dataBytes = File.ReadAllBytes(dataFilePath);

	//read everything from carrier image file into array of bytes
	Byte[] carrierBytes = File.ReadAllBytes(carrierFilePath);

	//converting password string into array of bytes
	Byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

	try
	{
		//embedding data to carrier
		Byte[] stegoBytes = StGBridge.StG.Embed(dataBytes, carrierBytes, passwordBytes);
	}
	catch (Exception ex)
	{
		//system will throw exception in case if carrier has not enough volume for given data
	}
  1. To extract data
	//read everything from stego image file into array of bytes
	Byte[] stegoBytes = File.ReadAllBytes(stegoFilePath);

	//converting password string into array of bytes
	Byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

	//extracting data from stego image
	Byte[] dataBytes = StGBridge.StG.Extract(stegoBytes, passwordBytes);

Python

As an example of usage in managed languages

  1. Obligatorily add OpenCV dll directory to Python paths
import os
os.add_dll_directory(r"C:\opencv\build\x64\vc16\bin")
  1. Use ctypes to load StGABI.dll
import ctypes
from ctypes import CDLL

dll_path = os.path.abspath(r"..\\x64\\Release\\StGABI.dll")
stgabi = CDLL(dll_path)
  1. Define .dll functions signatures
from ctypes import POINTER, c_uint8, c_size_t, c_int, c_double, c_void_p, byref

stgabi.Embed.argtypes = [
    POINTER(c_uint8), c_size_t,
    POINTER(c_uint8), c_size_t,
    POINTER(c_uint8), c_size_t,
    c_int, c_double,
    POINTER(POINTER(c_uint8)), POINTER(c_size_t)
]
stgabi.Embed.restype = c_int

stgabi.Extract.argtypes = [
    POINTER(c_uint8), c_size_t,
    POINTER(c_uint8), c_size_t,
    c_int, c_double,
    POINTER(POINTER(c_uint8)), POINTER(c_size_t)
]
stgabi.Extract.restype = c_int

stgabi.FreeMemory.argtypes = [c_void_p]
stgabi.FreeMemory.restype = None

embeddingBlockSize = 8
embeddingTreshold = 0.7
  1. Define Python helper functions
def read_bytes(path):
    with open(path, "rb") as f:
        return f.read()

def write_bytes(path, data):
    with open(path, "wb") as f:
        f.write(data)

def embed(data_path, carrier_path, password, stego_path):
    # Read file bytes
    data_bytes = read_bytes(data_path)
    carrier_bytes = read_bytes(carrier_path)
    password_bytes = bytearray(password, "utf-8")

    # Prepare pointers
    carrier_ptr = (c_uint8 * len(carrier_bytes))(*carrier_bytes)
    data_ptr = (c_uint8 * len(data_bytes))(*data_bytes)
    password_ptr = (c_uint8 * len(password_bytes))(*password_bytes)

    stego_ptr = POINTER(c_uint8)()
    stego_size = c_size_t()

    # Call C ABI function
    res = stgabi.Embed(
        data_ptr, len(data_bytes),
        carrier_ptr, len(carrier_bytes),
        password_ptr, len(password),
        embeddingBlockSize, embeddingTreshold,
        byref(stego_ptr), byref(stego_size)
    )

    if res != 0:
        raise RuntimeError(f"Embed failed with code {res}")

    # Convert result to Python bytes
    stego_bytes = string_at(stego_ptr, stego_size.value)

    # Write bytes to stego
    write_bytes(stego_path, stego_bytes)

    # Free memory
    stgabi.FreeMemory(stego_ptr)

    print(f"Embedded data into {stego_path}")

def extract(stego_path, password, extracted_path):
    # Read file bytes
    stego_bytes = read_bytes(stego_path)
    password_bytes = bytearray(password, "utf-8")

    # Prepare pointers
    stego_ptr = (c_uint8 * len(stego_bytes))(*stego_bytes)
    password_ptr = (c_uint8 * len(password_bytes))(*password_bytes)

    extracted_ptr = POINTER(c_uint8)()
    extracted_size = c_size_t()

    # Call C ABI function
    res = stgabi.Extract(
        stego_ptr, len(stego_bytes),
        password_ptr, len(password),
        embeddingBlockSize, embeddingTreshold,
        byref(extracted_ptr), byref(extracted_size)
    )

    if res != 0:
        raise RuntimeError(f"Extract failed with code {res}")

    # Convert result to Python bytes
    extracted_bytes = string_at(extracted_ptr, extracted_size.value)

    # Write bytes to result file
    write_bytes(extracted_path, extracted_bytes)

    # Free memory
    stgabi.FreeMemory(extracted_ptr)

    print(f"Extracted data to {extracted_path}")

Then, use this helper functions to embed and extract data.

Important! Always use stgabi.FreeBuffer() to free memory buffer after usage of stgabi.Embed() and stgabi.Extract() exactly as it shown above to avoid memory leaks.

Full source code of Python example you may find in file Python/example.py.

Notice, that functions of StGLib does not implement AES encryption. To add AES ciphering to your project you should use external libraries such as my Rijndael AESLib.


(back to Contents)

Roadmap of further development

  • Improve base functional
    • Reduce distributive size
  • Mobile OS versions
    • Android version
    • iOS version (donations for MacBook & iPhone required!)
  • More stego carriers - .bmp, .jpg
  • Stego-messenger - distributed, secured, free messenger for all main platforms
  • Advanced stego algorithms (ISGANs, DCT, DWT, RDH)
  • Text-based steganography

(back to Contents)

Support & donations

If you like this software, please, support me with donations. This will allow me to spend more time on improvement of my projects. Any help will count.

VISA card (Halyk bank, Worldwide): 4003 0351 5709 6871

МИР card (T-bank, Russia only): 2200 7021 5287 4603

Recepient: Daniil Galakhov


(back to Contents)

Legal notice

This software is distributing under MIT/BSD-like license. Full terms are available in the License file.

The project uses OpenCV Open Source Computer Vision Library. The OpenCV License requirements completed. OpenCV Copyright Notices provided in file OpenCV.txt.

Libertatian Stegosaurus Randall, who are a mascot of the project, desiged by author of the project. Logo image generated using ChatGPT 5.5.

carrier.png picture also was generated using ChatGPT 5.5.

App icon was created from logo image using PNG-to-ICO.


(back to Contents)

Contacts

Feel free to ask me through if you have any questions or offers. Use Issues for feedback.

About

App and C++ framework for hiding (or extraction) data in (or from) pictures using advanced steganography methods.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors