Skip to content

Instantly share code, notes, and snippets.

@hare1039
Last active December 31, 2020 18:20
Show Gist options
  • Save hare1039/d0470639c4957d3b04828962ebac427b to your computer and use it in GitHub Desktop.
Save hare1039/d0470639c4957d3b04828962ebac427b to your computer and use it in GitHub Desktop.
A simple steganography program stores data in png (red only)
#include <png++/png.hpp>
#include <iostream>
#include <memory>
#include <type_traits>
int constexpr bitmask = 0b00000011;
constexpr inline auto hash(char const * str, int h = 0) -> long long int {
return (!str[h] ? 5381 : (hash(str, h+1)*33) ^ str[h] );
}
constexpr inline auto operator "" _(char const * p, size_t) -> long long int { return hash(p); }
inline auto hash(std::string const & s) -> long long int { return hash (s.c_str()); }
auto bytestream(std::string const & input) -> std::vector<int>
{
std::vector<int> result;
std::size_t total = input.length() * 4 + 4;
result.push_back((total >> 0) & bitmask);
result.push_back((total >> 2) & bitmask);
result.push_back((total >> 4) & bitmask);
result.push_back((total >> 6) & bitmask);
for (char c : input)
{
result.push_back((c >> 0) & bitmask);
result.push_back((c >> 2) & bitmask);
result.push_back((c >> 4) & bitmask);
result.push_back((c >> 6) & bitmask);
}
return result;
}
auto decode(std::vector<int> const &data) -> std::string
{
std::string result;
auto it = data.begin();
std::size_t size =
*(it+0) << 0 |
*(it+1) << 2 |
*(it+2) << 4 |
*(it+3) << 6;
std::advance(it, 4);
for (; it != data.end() && std::distance(data.begin(), it) < size; std::advance(it, 4))
{
char size =
*(it+0) << 0 |
*(it+1) << 2 |
*(it+2) << 4 |
*(it+3) << 6;
result += size;
}
return result;
}
int main(int argc, char* argv[])
{
if (argc <= 2 or argc >= 5)
{
std::cerr << "hide-text [encrypt|decrypt] file.png [Your secret message]\n";
return 1;
}
std::string command = argv[1], pngfile = argv[2], message;
if (argc == 4)
message = argv[3];
png::image<png::rgba_pixel> image(pngfile);
switch (hash(command))
{
case "encrypt"_:
{
std::vector<int> bs = bytestream(message);
auto it = bs.begin();
for (png::uint_32 y = 0; y < image.get_height() && it != bs.end(); y++)
{
for (png::uint_32 x = 0; x < image.get_width() && it != bs.end(); x++)
{
png::rgba_pixel p = image.get_pixel(x, y);
auto v = p.red;
p.red = (p.red >> 2 << 2) | (*it++);
image.set_pixel(x, y, p);
}
}
image.set_compression_type(png::compression_type_default);
image.write(pngfile + ".encrypted.png");
break;
}
case "decrypt"_:
{
std::vector<int> data;
for (png::uint_32 y = 0; y < image.get_height(); y++)
{
for (png::uint_32 x = 0; x < image.get_width(); x++)
{
png::rgba_pixel p = image.get_pixel(x, y);
data.push_back(p.red & bitmask);
}
}
std::cout << decode(data) << "\n";
break;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment