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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
extern crate image;
use image::{GenericImageView, ImageBuffer};
use std::str;
#[cfg(test)]
mod tests;
mod file_helpers;
mod hider;
mod revealer;
mod bit_helpers;
use bit_helpers::{change_last_bit, get_bit_at, transform_u32_to_array_of_u8};
pub fn hide<'a>(payload_path: &str, carrier_path: &'a str) -> ImageBuffer<image::Rgb<u8>, Vec<u8>> {
let payload = file_helpers::get_file_string(payload_path);
let payload_bytes = payload.as_bytes();
let carrier = image::open(carrier_path).unwrap();
let (carrier_x_limit, carrier_y_limit) = carrier.dimensions();
let number_of_bytes_in_payload = payload_bytes.len() as u32;
if hider::is_payload_too_large(number_of_bytes_in_payload, carrier_x_limit, carrier_y_limit) {
panic!("Payload is too large for the carrier image");
};
let mut vec: Vec<u8> = Vec::with_capacity((number_of_bytes_in_payload + 4) as usize);
vec.extend_from_slice(&transform_u32_to_array_of_u8(number_of_bytes_in_payload));
vec.extend_from_slice(payload_bytes);
let mut byte_cursor = 8;
let mut bytes_to_hide = vec.iter();
let mut img: image::RgbImage = ImageBuffer::new(carrier_x_limit, carrier_y_limit);
let mut pixel_seen_count = 0;
let mut current_byte = *bytes_to_hide.next().unwrap();
for (x, y, pixel) in img.enumerate_pixels_mut() {
let carrier_pixel = carrier.get_pixel(x, y);
pixel_seen_count = pixel_seen_count + 1;
if pixel_seen_count <= (vec.len() * 3) {
if byte_cursor > 7 {
byte_cursor = 0;
};
*pixel = image::Rgb([
change_last_bit(carrier_pixel.data[0], get_bit_at(current_byte, byte_cursor)),
change_last_bit(
carrier_pixel.data[1],
get_bit_at(current_byte, byte_cursor + 1),
),
change_last_bit(
carrier_pixel.data[2],
get_bit_at(current_byte, byte_cursor + 2),
),
]);
byte_cursor = byte_cursor + 3;
if pixel_seen_count % 3 == 0 && pixel_seen_count != (vec.len() * 3) {
current_byte = *bytes_to_hide.next().unwrap();
}
} else {
*pixel = image::Rgb([
carrier_pixel.data[0],
carrier_pixel.data[1],
carrier_pixel.data[2],
]);
}
}
img
}
pub fn reveal(carrier_path: &str) -> String {
let carrier = image::open(carrier_path).unwrap();
let (carrier_x_limit, carrier_y_limit) = carrier.dimensions();
let message_header_length = 4;
let mut byte_cursor = 0;
let mut byte = 0b0000_0000;
let mut vec: Vec<u8> = Vec::new();
let mut byte_counter = 0;
let mut bytes_in_message: u32 = 5;
'outer: for y in 0..carrier_y_limit {
for x in 0..carrier_x_limit {
let carrier_pixel = carrier.get_pixel(x, y);
for i in 0..3 {
if byte_counter == bytes_in_message + message_header_length {
break 'outer;
}
if byte_cursor < 8 {
byte |= (get_bit_at(carrier_pixel.data[i], 0) as u8) << byte_cursor;
byte_cursor = byte_cursor + 1;
} else {
vec.push(byte);
byte_counter = byte_counter + 1;
if byte_counter == message_header_length {
bytes_in_message = revealer::get_number_of_bytes_in_message(vec.as_slice());
};
byte = 0b0000_0000;
byte_cursor = 0;
}
}
}
}
String::from(str::from_utf8(&vec[4..]).unwrap())
}