zindosteg 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,129 @@
1
+ #include "./permutator.h"
2
+ #include <openssl/evp.h>
3
+ #include "steg_endian.h"
4
+ #include <algorithm>
5
+
6
+ namespace zindorsky {
7
+ namespace permutator {
8
+
9
+ namespace {
10
+ struct key_cstr_helper {
11
+ key_cstr_helper(crypto::key_generator const& generator, size_t len)
12
+ : key(len)
13
+ {
14
+ generator.generate(key.data(), key.size());
15
+ }
16
+
17
+ byte_vector key;
18
+ };
19
+ } //namespace
20
+
21
+ context::context(index_t array_size, crypto::key_generator const& generator, int keylen)
22
+ : context{array_size, key_cstr_helper{generator, static_cast<size_t>(keylen)}.key.data(), keylen}
23
+ {
24
+ }
25
+
26
+ context::context(index_t array_size, byte const* key, int keylen)
27
+ : context{array_size, crypto::aes{key, keylen}}
28
+ {
29
+ }
30
+
31
+ context::context(index_t array_size, crypto::aes const& key)
32
+ : size_{array_size}
33
+ , key_{key}
34
+ {
35
+ for(bitlen_=0; array_size!=0; ++bitlen_)
36
+ array_size >>= 1;
37
+ split_ = bitlen_/2;
38
+ split_mask_[0] = (1<<split_)-1;
39
+ split_mask_[1] = (1<<((bitlen_+1)/2))-1;
40
+
41
+ if( bitlen_ <= 9 ) {
42
+ rounds_ = 36;
43
+ } else if( bitlen_ <= 13 ) {
44
+ rounds_ = 30;
45
+ } else if( bitlen_ <= 19 ) {
46
+ rounds_ = 24;
47
+ } else if( bitlen_ <= 31 ) {
48
+ rounds_ = 18;
49
+ } else {
50
+ rounds_ = 12;
51
+ }
52
+
53
+ //Pre-compute AES(P)
54
+ //VERS
55
+ P_templ_[0] = 0; P_templ_[1]=1;
56
+ //method
57
+ P_templ_[2] = 2;
58
+ //addition
59
+ P_templ_[3] = 0;
60
+ //radix
61
+ P_templ_[4] = 2;
62
+ //n
63
+ P_templ_[5] = bitlen_;
64
+ //split(n)
65
+ P_templ_[6] = split_;
66
+ //rnds(n)
67
+ P_templ_[7] = rounds_;
68
+ //tweak length (no tweak in this implementation)
69
+ std::fill_n(&P_templ_[8], 8, 0);
70
+ key_.encrypt(P_templ_,P_templ_);
71
+ }
72
+
73
+ //AES-FFX-A2 encrypt
74
+ index_t context::operator[] (index_t index) const
75
+ {
76
+ half_t A = static_cast<half_t>( index & split_mask_[0] );
77
+ half_t B = static_cast<half_t>( index >> split_ );
78
+
79
+ for(byte i=0; i<rounds_; ++i) {
80
+ half_t C = A ^ F(i,B);
81
+ A = B;
82
+ B = C;
83
+ }
84
+
85
+ index_t retval = (static_cast<index_t>(B)<<split_) | static_cast<index_t>(A);
86
+
87
+ //Chain-walking:
88
+ if( retval >= size_ ) {
89
+ return operator[](retval);
90
+ }
91
+ return retval;
92
+ }
93
+
94
+ //AES-FFX-A2 decrypt
95
+ index_t context::reverse(index_t index) const
96
+ {
97
+ half_t A = static_cast<half_t>( index & split_mask_[0] );
98
+ half_t B = static_cast<half_t>( index >> split_ );
99
+
100
+ for(byte i=rounds_; i>0; --i) {
101
+ half_t C = B;
102
+ B = A;
103
+ A = C ^ F(i-1,B);
104
+ }
105
+
106
+ index_t retval = (static_cast<index_t>(B)<<split_) | static_cast<index_t>(A);
107
+
108
+ //Chain-walking:
109
+ if( retval >= size_ ) {
110
+ return reverse(retval);
111
+ }
112
+ return retval;
113
+ }
114
+
115
+ context::half_t context::F(byte r, half_t B) const
116
+ {
117
+ byte Q[AES_BLOCK_SIZE] = {0};
118
+ //Fill out Q. (No tweak in this implementation.)
119
+ Q[7] = r;
120
+ endian::write_be(B,&Q[sizeof(Q)-sizeof(B)]);
121
+ for(std::size_t i=0; i<sizeof(Q); ++i) {
122
+ Q[i] ^= P_templ_[i];
123
+ }
124
+ key_.encrypt(Q,Q);
125
+ endian::read_be(&Q[sizeof(Q)-sizeof(B)],B);
126
+ return B & split_mask_[r%2];
127
+ }
128
+
129
+ }} //namespace zindorsky::permutator
@@ -0,0 +1,39 @@
1
+ #pragma once
2
+
3
+ /* An implementation of the AES-FFX-A2 algorithm as a means to a low-memory, random-access, cryptographically-strong, index permutator.
4
+ See http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ffx/ffx-spec.pdf for the spec.
5
+ */
6
+
7
+ #include "steg_defs.h"
8
+ #include <cstring>
9
+ #include "aes.h"
10
+ #include "key_generator.h"
11
+ #include <cstdint>
12
+
13
+ namespace zindorsky {
14
+ namespace permutator {
15
+
16
+ using index_t = uint_fast64_t;
17
+
18
+ class context {
19
+ public:
20
+ context(index_t array_size, crypto::key_generator const& generator, int keylen = 16);
21
+ context(index_t array_size, byte const* key, int keylen = 16);
22
+ context(index_t array_size, crypto::aes const& key);
23
+
24
+ index_t operator[] (index_t index) const;
25
+ index_t reverse (index_t index) const;
26
+
27
+ private:
28
+ using half_t = uint_fast32_t;
29
+
30
+ index_t size_;
31
+ crypto::aes key_;
32
+ byte bitlen_, split_, rounds_;
33
+ byte P_templ_[AES_BLOCK_SIZE];
34
+ half_t split_mask_[2];
35
+
36
+ half_t F(byte r, half_t B) const;
37
+ };
38
+
39
+ }} //namespace zindorsky::permutator
@@ -0,0 +1,304 @@
1
+ #include "png_provider.h"
2
+ #include <exception>
3
+ #include "file_utils.h"
4
+ #include "string.h"
5
+
6
+ namespace zindorsky {
7
+ namespace steganography {
8
+
9
+ namespace {
10
+
11
+ struct read_context {
12
+ read_context(byte const* data, size_t size) : data{data}, size{size} {}
13
+ byte const* data;
14
+ size_t size;
15
+ size_t pos = 0;
16
+ };
17
+
18
+ void read_data(png_structp png_ptr, png_bytep data, png_size_t length)
19
+ {
20
+ auto source = reinterpret_cast<read_context*>(png_get_io_ptr(png_ptr));
21
+ if (source->pos + length >= source->size) {
22
+ length = source->size - source->pos;
23
+ }
24
+ memcpy(data, source->data + source->pos, length);
25
+ source->pos += length;
26
+ }
27
+
28
+ void write_data(png_structp png_ptr, png_bytep data, png_size_t length)
29
+ {
30
+ byte_vector* sink = reinterpret_cast<byte_vector*>(png_get_io_ptr(png_ptr));
31
+ sink->insert(sink->end(), data, data + length);
32
+ }
33
+
34
+ void flush_data(png_structp)
35
+ {
36
+ }
37
+
38
+ } //namespace
39
+
40
+ const byte png_provider::signature[8] = {0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A};
41
+
42
+ png_provider::png_provider(filesystem::path const& filename)
43
+ : png_provider( utils::load_from_file(filename) )
44
+ {
45
+ }
46
+
47
+ png_provider::png_provider(byte_vector const& data)
48
+ : png_provider(data.data(), data.size())
49
+ {
50
+ }
51
+
52
+ png_provider::png_provider(byte const* data, size_t size)
53
+ {
54
+ if(size < sizeof(signature) || memcmp(data, signature, sizeof(signature))!=0) {
55
+ throw invalid_carrier();
56
+ }
57
+
58
+ ctx_ = std::make_unique<png_read_ctx>();
59
+ if (setjmp(png_jmpbuf(ctx_->ptr))) {
60
+ throw invalid_carrier();
61
+ }
62
+
63
+ read_context read_ctx{data, size};
64
+ png_set_read_fn(ctx_->ptr, &read_ctx, read_data);
65
+
66
+ png_read_info(ctx_->ptr, ctx_->info);
67
+
68
+ width_ = png_get_image_width(ctx_->ptr, ctx_->info);
69
+ height_ = png_get_image_height(ctx_->ptr, ctx_->info);
70
+ bit_depth_ = png_get_bit_depth(ctx_->ptr, ctx_->info);
71
+ color_type_ = png_get_color_type(ctx_->ptr, ctx_->info);
72
+
73
+ if( (color_type_==0 && bit_depth_!=1 && bit_depth_!=2 && bit_depth_!=4 && bit_depth_!=8 && bit_depth_!=16)
74
+ || ((color_type_==2 || color_type_==4 || color_type_==6) && bit_depth_!=8 && bit_depth_!=16)
75
+ || (color_type_==3 &&bit_depth_!=1 && bit_depth_!=2 && bit_depth_!=4 && bit_depth_!=8)
76
+ ) {
77
+ throw invalid_carrier();
78
+ }
79
+
80
+ //We're going to disallow images with bit depth less than 8, since hidden data is more noticeable in them.
81
+ if(bit_depth_ < 8) {
82
+ throw invalid_carrier("PNG bit depth too small");
83
+ }
84
+ //Palette types are also not good for steganography:
85
+ if(color_type_ & 1) {
86
+ throw invalid_carrier("palette using PNG files not supported");
87
+ }
88
+
89
+ auto row_size = png_get_rowbytes(ctx_->ptr, ctx_->info);
90
+ data_.resize(row_size * height_);
91
+ row_pointers_.resize(height_);
92
+ for(auto i = 0U; i < height_; ++i) {
93
+ row_pointers_[i] = &data_[0] + i * row_size;
94
+ }
95
+ png_read_image(ctx_->ptr, &row_pointers_[0]);
96
+ }
97
+
98
+ provider_t::index_t png_provider::size() const
99
+ {
100
+ return data_.size() / (bit_depth_ / 8);
101
+ }
102
+
103
+ byte & png_provider::access_indexed_data(provider_t::index_t index)
104
+ {
105
+ return data_[adjust_index(index)];
106
+ }
107
+
108
+ byte const& png_provider::access_indexed_data(index_t index) const
109
+ {
110
+ return data_[adjust_index(index)];
111
+ }
112
+
113
+ byte_vector png_provider::commit_to_memory()
114
+ {
115
+ byte_vector data;
116
+ png_write_ctx write_ctx;
117
+ if (setjmp(png_jmpbuf(write_ctx.ptr))) {
118
+ throw std::exception();
119
+ }
120
+ png_set_write_fn(write_ctx.ptr, &data, write_data, flush_data);
121
+ write_ctx.copy_from_read(*ctx_);
122
+
123
+ png_write_info(write_ctx.ptr, write_ctx.info);
124
+ png_write_image(write_ctx.ptr, &row_pointers_[0]);
125
+ png_write_end(write_ctx.ptr, nullptr);
126
+
127
+ return data;
128
+ }
129
+
130
+ void png_provider::commit_to_file(filesystem::path const& file)
131
+ {
132
+ FILE *f = fopen(file.string().c_str(), "wb");
133
+ png_write_ctx write_ctx;
134
+ if (setjmp(png_jmpbuf(write_ctx.ptr))) {
135
+ if(f) fclose(f);
136
+ throw std::exception();
137
+ }
138
+ png_init_io(write_ctx.ptr, f);
139
+ write_ctx.copy_from_read(*ctx_);
140
+
141
+ png_write_info(write_ctx.ptr, write_ctx.info);
142
+ png_write_image(write_ctx.ptr, &row_pointers_[0]);
143
+ png_write_end(write_ctx.ptr, nullptr);
144
+ fclose(f);
145
+ }
146
+
147
+ byte_vector png_provider::salt() const
148
+ {
149
+ byte salt[8]={0};
150
+ for(std::size_t i=0; i<height_; ++i) {
151
+ salt[ i%sizeof(salt) ] += access_indexed_data(i*width_ + i%width_)>>1;
152
+ }
153
+
154
+ return byte_vector(salt,salt+sizeof(salt));
155
+ }
156
+
157
+ size_t png_provider::adjust_index(size_t index) const
158
+ {
159
+ return index * (bit_depth_ / 8);
160
+ }
161
+
162
+
163
+ void png_write_ctx::copy_from_read(png_read_ctx const& read_ctx)
164
+ {
165
+ std::uint32_t width, height;
166
+ int bit_depth, color_type;
167
+ int interlace_type, compression_type, filter_type;
168
+
169
+ if (png_get_IHDR(read_ctx.ptr, read_ctx.info, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type))
170
+ png_set_IHDR(ptr, info, width, height, bit_depth,
171
+ #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
172
+ color_type, interlace_type, compression_type, filter_type
173
+ #else
174
+ color_type, PNG_INTERLACE_NONE, compression_type, filter_type
175
+ #endif
176
+ );
177
+ #if defined(PNG_FIXED_POINT_SUPPORTED)
178
+ #if defined(PNG_cHRM_SUPPORTED)
179
+ png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
180
+ if (png_get_cHRM_fixed(read_ctx.ptr, read_ctx.info, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y))
181
+ png_set_cHRM_fixed(ptr, info, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
182
+ #endif
183
+ #if defined(PNG_gAMA_SUPPORTED)
184
+ png_fixed_point gamma;
185
+ if (png_get_gAMA_fixed(read_ctx.ptr, read_ctx.info, &gamma))
186
+ png_set_gAMA_fixed(ptr, info, gamma);
187
+ #endif
188
+ #else /* Use floating point versions */
189
+ #if defined(PNG_FLOATING_POINT_SUPPORTED)
190
+ #if defined(PNG_cHRM_SUPPORTED)
191
+ double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
192
+ if (png_get_cHRM(read_ctx.ptr, read_ctx.info, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y))
193
+ png_set_cHRM(ptr, info, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
194
+ #endif
195
+ #if defined(PNG_gAMA_SUPPORTED)
196
+ double gamma;
197
+ if (png_get_gAMA(read_ctx.ptr, read_ctx.info, &gamma))
198
+ png_set_gAMA(ptr, info, gamma);
199
+ #endif
200
+ #endif /* floating point */
201
+ #endif /* fixed point */
202
+ #if defined(PNG_iCCP_SUPPORTED)
203
+ png_charp name;
204
+ png_bytep profile;
205
+ png_uint_32 proflen;
206
+ if (png_get_iCCP(read_ctx.ptr, read_ctx.info, &name, &compression_type, &profile, &proflen))
207
+ png_set_iCCP(ptr, info, name, compression_type, profile, proflen);
208
+ #endif
209
+ #if defined(PNG_sRGB_SUPPORTED)
210
+ int intent;
211
+ if (png_get_sRGB(read_ctx.ptr, read_ctx.info, &intent))
212
+ png_set_sRGB(ptr, info, intent);
213
+ #endif
214
+ png_colorp palette;
215
+ int num_palette;
216
+ if (png_get_PLTE(read_ctx.ptr, read_ctx.info, &palette, &num_palette))
217
+ png_set_PLTE(ptr, info, palette, num_palette);
218
+ #if defined(PNG_bKGD_SUPPORTED)
219
+ png_color_16p background;
220
+ if (png_get_bKGD(read_ctx.ptr, read_ctx.info, &background))
221
+ png_set_bKGD(ptr, info, background);
222
+ #endif
223
+ #if defined(PNG_hIST_SUPPORTED)
224
+ png_uint_16p hist;
225
+ if (png_get_hIST(read_ctx.ptr, read_ctx.info, &hist))
226
+ png_set_hIST(ptr, info, hist);
227
+ #endif
228
+ #if defined(PNG_oFFs_SUPPORTED)
229
+ png_int_32 offset_x, offset_y;
230
+ int unit_type;
231
+ if (png_get_oFFs(read_ctx.ptr, read_ctx.info,&offset_x,&offset_y,&unit_type))
232
+ png_set_oFFs(ptr, info, offset_x, offset_y, unit_type);
233
+ #endif
234
+ #if defined(PNG_pCAL_SUPPORTED)
235
+ png_charp purpose, units;
236
+ png_charpp params;
237
+ png_int_32 X0, X1;
238
+ int type, nparams;
239
+
240
+ if (png_get_pCAL(read_ctx.ptr, read_ctx.info, &purpose, &X0, &X1, &type, &nparams, &units, &params))
241
+ png_set_pCAL(ptr, info, purpose, X0, X1, type, nparams, units, params);
242
+ #endif
243
+ #if defined(PNG_pHYs_SUPPORTED)
244
+ png_uint_32 res_x, res_y;
245
+ if (png_get_pHYs(read_ctx.ptr, read_ctx.info, &res_x, &res_y, &unit_type))
246
+ png_set_pHYs(ptr, info, res_x, res_y, unit_type);
247
+ #endif
248
+ #if defined(PNG_sBIT_SUPPORTED)
249
+ png_color_8p sig_bit;
250
+
251
+ if (png_get_sBIT(read_ctx.ptr, read_ctx.info, &sig_bit))
252
+ png_set_sBIT(ptr, info, sig_bit);
253
+ #endif
254
+ #if defined(PNG_sCAL_SUPPORTED)
255
+ #ifdef PNG_FLOATING_POINT_SUPPORTED
256
+ int unit;
257
+ double scal_width, scal_height;
258
+
259
+ if (png_get_sCAL(read_ctx.ptr, read_ctx.info, &unit, &scal_width, &scal_height))
260
+ png_set_sCAL(ptr, info, unit, scal_width, scal_height);
261
+ #else
262
+ #ifdef PNG_FIXED_POINT_SUPPORTED
263
+ int unit;
264
+ png_charp scal_width, scal_height;
265
+
266
+ if (png_get_sCAL_s(read_ctx.ptr, read_ctx.info, &unit, &scal_width, &scal_height))
267
+ png_set_sCAL_s(ptr, info, unit, scal_width, scal_height);
268
+ #endif
269
+ #endif
270
+ #endif
271
+ #if defined(PNG_TEXT_SUPPORTED)
272
+ png_textp text_ptr;
273
+ int num_text;
274
+ if (png_get_text(read_ctx.ptr, read_ctx.info, &text_ptr, &num_text) > 0)
275
+ png_set_text(ptr, info, text_ptr, num_text);
276
+ #endif
277
+ #if defined(PNG_tIME_SUPPORTED)
278
+ png_timep mod_time;
279
+
280
+ if (png_get_tIME(read_ctx.ptr, read_ctx.info, &mod_time)) {
281
+ png_set_tIME(ptr, info, mod_time);
282
+ }
283
+ #endif
284
+ #if defined(PNG_tRNS_SUPPORTED)
285
+ png_bytep trans;
286
+ int num_trans;
287
+ png_color_16p trans_values;
288
+ if (png_get_tRNS(read_ctx.ptr, read_ctx.info, &trans, &num_trans, &trans_values))
289
+ png_set_tRNS(ptr, info, trans, num_trans, trans_values);
290
+ #endif
291
+ #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
292
+ png_unknown_chunkp unknowns;
293
+ int num_unknowns = (int)png_get_unknown_chunks(read_ctx.ptr, read_ctx.info, &unknowns);
294
+ if (num_unknowns) {
295
+ png_size_t i;
296
+ png_set_unknown_chunks(ptr, info, unknowns, num_unknowns);
297
+ for (i = 0; i < num_unknowns; i++)
298
+ png_set_unknown_chunk_location(ptr, info, i, unknowns[i].location);
299
+ }
300
+ #endif
301
+ }
302
+
303
+ }} //namespace
304
+
@@ -0,0 +1,87 @@
1
+ #pragma once
2
+
3
+ #include "provider.h"
4
+ #include <vector>
5
+ #include <cstdint>
6
+ #include <png.h>
7
+ #include <memory>
8
+
9
+ namespace zindorsky {
10
+ namespace steganography {
11
+
12
+ struct png_read_ctx {
13
+ png_structp ptr = nullptr;
14
+ png_infop info = nullptr;
15
+
16
+ png_read_ctx()
17
+ {
18
+ ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
19
+ if (ptr) {
20
+ info = png_create_info_struct(ptr);
21
+ }
22
+ }
23
+
24
+ ~png_read_ctx()
25
+ {
26
+ if(ptr) {
27
+ png_destroy_read_struct(&ptr, info ? &info : nullptr, nullptr);
28
+ }
29
+ }
30
+ };
31
+
32
+ struct png_write_ctx {
33
+ png_structp ptr = nullptr;
34
+ png_infop info = nullptr;
35
+
36
+ png_write_ctx()
37
+ {
38
+ ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
39
+ if (ptr) {
40
+ info = png_create_info_struct(ptr);
41
+ }
42
+ }
43
+
44
+ ~png_write_ctx()
45
+ {
46
+ if(ptr) {
47
+ png_destroy_write_struct(&ptr, info ? &info : nullptr);
48
+ }
49
+ }
50
+
51
+ void copy_from_read(png_read_ctx const& read_ctx);
52
+ };
53
+
54
+ class png_provider : public provider_t {
55
+ public:
56
+ explicit png_provider(filesystem::path const& filename);
57
+ explicit png_provider(byte_vector const& data);
58
+ png_provider(byte const* data, size_t size);
59
+
60
+ //Non-copyable:
61
+ png_provider(png_provider const&) = delete;
62
+ png_provider & operator = (png_provider const&) = delete;
63
+ //Movable:
64
+ png_provider(png_provider &&) = default;
65
+ png_provider & operator = (png_provider &&) = default;
66
+
67
+ static std::string format() { return "PNG"; }
68
+ virtual index_t size() const override;
69
+ virtual byte & access_indexed_data(index_t index) override;
70
+ virtual byte const& access_indexed_data(index_t index) const override;
71
+ virtual byte_vector commit_to_memory() override;
72
+ virtual void commit_to_file(filesystem::path const& file) override;
73
+ virtual byte_vector salt() const override;
74
+
75
+ static const byte signature[8];
76
+
77
+ private:
78
+ std::unique_ptr<png_read_ctx> ctx_;
79
+ byte_vector data_;
80
+ std::vector<byte*> row_pointers_;
81
+ std::uint32_t width_, height_;
82
+ byte bit_depth_, color_type_;
83
+
84
+ size_t adjust_index(size_t index) const;
85
+ };
86
+
87
+ }} //namespace zindorsky::steganography
@@ -0,0 +1,40 @@
1
+ #pragma once
2
+
3
+ #include "steg_defs.h"
4
+ #include <vector>
5
+ #include <memory>
6
+ #include <cstdint>
7
+ #include <exception>
8
+
9
+ namespace zindorsky {
10
+ namespace steganography {
11
+
12
+ class invalid_carrier : public std::runtime_error {
13
+ public:
14
+ invalid_carrier() : std::runtime_error{"Invalid carrier file"} {}
15
+ explicit invalid_carrier(char const* msg) : std::runtime_error{msg} {}
16
+ };
17
+
18
+ class provider_t {
19
+ public:
20
+ //Loads from file.
21
+ static std::unique_ptr<provider_t> load(filesystem::path const& file);
22
+ //Loads from memory. Caller retains ownership of buffer.
23
+ static std::unique_ptr<provider_t> load(void const* data, size_t size);
24
+
25
+ static std::vector<std::string> supported_formats();
26
+
27
+ using index_t = uint_fast64_t;
28
+
29
+ virtual ~provider_t() {}
30
+
31
+ virtual index_t size() const = 0;
32
+ virtual byte & access_indexed_data(index_t index) = 0;
33
+ virtual byte const& access_indexed_data( index_t index ) const = 0;
34
+ virtual byte_vector commit_to_memory() = 0;
35
+ virtual void commit_to_file(filesystem::path const& file) = 0;
36
+ virtual byte_vector salt() const = 0;
37
+
38
+ };
39
+
40
+ }} //namespace zindorsky::steganography
@@ -0,0 +1,24 @@
1
+ #pragma once
2
+
3
+ #include <vector>
4
+ #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 9
5
+ # define EXPERIMENTAL_FILESYSTEM
6
+ # include <experimental/filesystem>
7
+ #else
8
+ # include <filesystem>
9
+ #endif
10
+
11
+ namespace zindorsky {
12
+
13
+ using byte = unsigned char;
14
+ using byte_vector = std::vector<byte>;
15
+
16
+ #if defined(EXPERIMENTAL_FILESYSTEM)
17
+ # include <experimental/filesystem>
18
+ namespace filesystem = std::experimental::filesystem;
19
+ #else
20
+ # include <filesystem>
21
+ namespace filesystem = std::filesystem;
22
+ #endif
23
+
24
+ } // namespace zindorsky