Skip to content

Instantly share code, notes, and snippets.

@EIREXE
Created January 30, 2018 01:37
Show Gist options
  • Save EIREXE/736d80cd1299c3b019549899da5faa5b to your computer and use it in GitHub Desktop.
Save EIREXE/736d80cd1299c3b019549899da5faa5b to your computer and use it in GitHub Desktop.
Steganography for the godot engine
extends Node
const STEGANO_MAGIC_NUMBER = [0x45, 0x52, 0x4f, 0x31] #ERO1
const STEGANO_CHUNK_END = [0x45, 0x52, 0x4f, 0x45] #EROE
const BITS_PER_BYTE = 2 # How many bits we take from each one, 1 is the least singificant bit
const STEGANO_FORMAT_VERSION = 1
func store_string_in_image(image ,data):
print(data)
var text_binary = data.to_utf8().compress()
var text_compressed = text_binary.compress()
var payload = PoolByteArray(STEGANO_MAGIC_NUMBER)
payload.append(text_binary.size())
payload.append(STEGANO_FORMAT_VERSION)
payload.append_array(text_compressed)
payload.append_array(PoolByteArray(STEGANO_CHUNK_END))
return store_data_in_image(image, payload)
func store_data_in_image(image, data):
var image_data = image.get_data()
var writing_mask = 0
for mask_i in range(BITS_PER_BYTE):
writing_mask = writing_mask | (0x1 << mask_i)
var image_position = 0
for byte_i in range(data.size()):
var images_bytes_per_byte = 8/BITS_PER_BYTE
for insert_i in range(images_bytes_per_byte):
var insertion_mask = writing_mask << insert_i * MBITS_PER_BYTE
var bits_to_write = data[byte_i] & insertion_mask
bits_to_write = bits_to_write >> insert_i*BITS_PER_BYTE
var image_data_mask = 0xFF >> BITS_PER_BYTE
image_data_mask = image_data_mask << BITS_PER_BYTE
image_data[image_position+insert_i] = image_data[image_position+insert_i] & image_data_mask
image_data[image_position+insert_i] = image_data[image_position+insert_i] | bits_to_write
image_position += images_bytes_per_byte
var final_image = Image.new()
final_image.create_from_data(image.get_width(), image.get_height(), false, Image.FORMAT_RGB8, image_data)
return final_image
func get_steganographic_data_from_image(image):
extracted_data = PoolByteArray()
var image_data = image.get_data()
var data_mask = 0
for mask_i in range(BITS_PER_BYTE):
data_mask = data_mask | (0x1 << mask_i)
var current_byte = 0
var magic_number_position = -1
for byte_i in range(image_data.size()):
var data = image_data[byte_i] & data_mask
var iterations_per_byte = 8/BITS_PER_BYTE
var current_bits = data & data_mask
current_byte = current_byte | (current_bits << ((byte_i % iterations_per_byte)*BITS_PER_BYTE))
# 0 index bullcrap...
if byte_i % iterations_per_byte == iterations_per_byte-1:
extracted_data.append(current_byte)
if byte_i < 64:
pass
current_byte = 0
if extracted_data.size() >= 4:
var potential_magic_number = extracted_data.subarray(extracted_data.size()-PoolByteArray(STEGANO_MAGIC_NUMBER).size(), extracted_data.size()-1)
if potential_magic_number == PoolByteArray(STEGANO_MAGIC_NUMBER):
magic_number_position = extracted_data.size()-1
var potential_chunk_end = extracted_data.subarray(extracted_data.size()-PoolByteArray(STEGANO_CHUNK_END).size(), extracted_data.size()-1)
if potential_chunk_end == PoolByteArray(STEGANO_CHUNK_END):
break
if magic_number_position != -1:
var uncompressed_size_position = magic_number_position+1
var uncompressed_size = extracted_data[uncompressed_size_position]
var version_number = magic_number_position+2
var compressed_data_position = magic_number_position+3
var compressed_data = extracted_data.subarray(compressed_data_position, extracted_data.size()-5)
var uncompressed_data = compressed_data.decompress(uncompressed_size).get_string_from_utf8()
return uncompressed_data
else:
return ERR_FILE_CORRUPT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment