-
Notifications
You must be signed in to change notification settings - Fork 0
/
set_steg_data.go
435 lines (349 loc) · 13.8 KB
/
set_steg_data.go
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
package main
import (
"encoding/binary"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
)
// HiddenFileData: Data structure that describes the file hidden in the container file
type HiddenFileData struct {
magicNumber int64
fileName [FILENAME_LENGTH]byte
steps int64
spacing int64
}
// Steg: Places the hide file data in to the container file data
func Steg(_containerFile string, _hideFile string) bool {
var fileHidden bool = true
var containerFileSize int64 = 0
var hideFileSize int64 = 0
const START_OFFSET int64 = 2000
const BUFFER_SIZE int64 = 1000
var spaceAvailable int64 = 0
var spacing int64 = 0
var countSpacing int64 = 0
var containerFile *os.File
var hiddenFile *os.File
var buffer []byte
var writeCounter int64 = 0
var writeByte []byte
var err error
var containerFileWriteError bool = false
var hiddenFileBytesRead int = 0
var hiddenFileTotalBytesRead int = 0
var containerFileBytesWritten int = 0
var containerFileTotalBytesWritten int64 = 0
var stepsCount int64 = 0
// If file names for container and file to hide have been passed in
if len(_containerFile) > 0 && len(_hideFile) > 0 {
// If container file exists
if FileExists(_containerFile) {
// If file to hide exists
if FileExists(_hideFile) {
// Get container file size
containerFileSize = GetFileSize(_containerFile)
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_FileSize, _containerFile, containerFileSize))
}
// If container file size is valid
if containerFileSize != -1 && containerFileSize > 0 {
// Get file to hide file size
hideFileSize = GetFileSize(_hideFile)
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_FileSize, _hideFile, hideFileSize))
}
// If file to hide file size is valid
if hideFileSize != -1 && hideFileSize > 0 {
// Check if file to hide will fit into container file
// File to hide size must be no bigger than 10% of the container file size minus the start offset
spaceAvailable = containerFileSize - START_OFFSET
if spaceAvailable > 0 {
spaceAvailable = spaceAvailable * 10 / 100
if spaceAvailable > 0 {
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_SpaceAvailable, spaceAvailable))
}
if spaceAvailable > hideFileSize {
// File to hide will fit inside container file
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_FileToHideFits, _hideFile, _containerFile))
}
// Calculate spacing - locations in container file to write hidden file data to
spacing = (containerFileSize - START_OFFSET) / hideFileSize
if spacing > 0 {
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_UsingSpacing, spacing))
}
// Set initial location in container file to write hidden file data to
countSpacing = START_OFFSET + 1
// Open container file
containerFile, err = os.OpenFile(_containerFile, os.O_WRONLY, 0)
if err == nil {
// Open file to hide
hiddenFile, err = os.OpenFile(_hideFile, os.O_RDONLY, 0)
if err == nil {
// Work through file to hide writing its data into the container file
for {
// Set up buffer to read file to hide data into
if hideFileSize < BUFFER_SIZE {
buffer = make([]byte, hideFileSize)
} else {
buffer = make([]byte, BUFFER_SIZE)
}
if int64(len(buffer)) == BUFFER_SIZE || int64(len(buffer)) == hideFileSize {
// Read the file to hide data into the buffer
hiddenFileBytesRead, err = hiddenFile.Read(buffer)
hiddenFileTotalBytesRead += hiddenFileBytesRead
if err != nil {
if err == io.EOF {
// If end of file to hide found, stop writing its data to the container file
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_EOF, _hideFile))
}
break
} else {
// Error reading file to hide - display an error and stop writing data
fmt.Println(fmt.Sprintf(UI_FileReadError, _containerFile, err))
fileHidden = false
containerFileWriteError = true
break
}
} else {
// Loop around file to hide buffer writing buffer data to container file one byte at a time
for writeCounter = 0; writeCounter != int64(len(buffer)); writeCounter++ {
if UPDATE_UI == true {
// Update UI
fmt.Printf("\r" + fmt.Sprintf(UI_HiddenDataWriting, _hideFile, _containerFile) + ". ")
}
// Get a byte from the buffer
writeByte = append(writeByte, buffer[writeCounter])
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_WritingToLocation, countSpacing))
}
// Write the byte to container file at spacing location
containerFileBytesWritten, err = containerFile.WriteAt(writeByte, countSpacing)
stepsCount++
// Move on to the next spacing location
countSpacing = countSpacing + spacing
if UPDATE_UI == true {
// Update UI
fmt.Printf("\r" + fmt.Sprintf(UI_HiddenDataWriting, _hideFile, _containerFile) + ".. ")
}
if err != nil {
if err == io.EOF {
// If end of container file found, display an error and stop writing to it and display end of file
fmt.Println(fmt.Sprintf(UI_EOF, _containerFile))
fileHidden = false
containerFileWriteError = true
break
} else {
// Error writing to container file - display an error and stop writing data
fmt.Println(fmt.Sprintf(UI_FileWriteError, _containerFile, err))
fileHidden = false
containerFileWriteError = true
break
}
} else {
// If the byte not written to the container file - display an error and stop writing data
if containerFileBytesWritten != len(writeByte) {
fmt.Println(fmt.Sprintf(UI_FileWriteError, _containerFile, ""))
fileHidden = false
containerFileWriteError = true
break
} else {
// Clear the byte out
writeByte = nil
// Keep track of amount of data written to the container file
containerFileTotalBytesWritten = containerFileTotalBytesWritten + int64(containerFileBytesWritten)
// If amount of data written to the container file is the same as the file to hide size, all file to hide data has been written to the container file - stop writing data
if containerFileTotalBytesWritten == hideFileSize {
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_HiddenDataWrittenOK, _hideFile, _containerFile))
}
break
}
}
}
if UPDATE_UI == true {
// Update UI
fmt.Printf("\r" + fmt.Sprintf(UI_HiddenDataWriting, _hideFile, _containerFile) + "...")
}
} // end byte at a time for loop
if DEBUG == true {
if containerFileWriteError == true {
// Container file written to with errors
fmt.Println(fmt.Sprintf(UI_FileWriteError, _containerFile, ""))
}
}
}
} else {
// Failed to allocate buffer memory
fmt.Println(UI_NoBufferMemory)
fileHidden = false
containerFileWriteError = true
break
}
buffer = nil
} // End read file to hide for loop
// Write hidden file data to container file
if containerFileWriteError == false {
if WriteHiddenFileData(containerFile, _hideFile, stepsCount, spacing) == false {
fmt.Println(fmt.Sprintf(UI_FileWriteError, containerFile.Name(), ""))
fileHidden = false
}
}
if UPDATE_UI == true {
// Update UI
fmt.Printf("\r")
}
} else {
// Open file to hide error
fmt.Println(UI_FileOpenError, err)
fileHidden = false
}
} else {
// Open container file error
fmt.Println(UI_FileOpenError, err)
fileHidden = false
}
// File to hide data written to contain file OK - close file handles down and clear buffer
containerFile.Sync()
containerFile.Close()
hiddenFile.Close()
buffer = nil
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_HiddenFileData, spacing, stepsCount, _hideFile))
}
} else {
fmt.Println(fmt.Sprintf(UI_SpacingError, _hideFile, _containerFile))
fileHidden = false
}
} else {
fmt.Println(fmt.Sprintf(UI_SpacingError, _hideFile, _containerFile))
fileHidden = false
}
} else {
fmt.Println(fmt.Sprintf(UI_SpacingError, _hideFile, _containerFile))
fileHidden = false
}
} else {
fmt.Println(fmt.Sprintf(UI_SpacingError, _hideFile, _containerFile))
fileHidden = false
}
} else {
fmt.Println(UI_InvalidFileSize, _hideFile)
fileHidden = false
}
} else {
fmt.Println(UI_InvalidFileSize, _containerFile)
fileHidden = false
}
} else {
fmt.Println(UI_FileNotFound, _hideFile)
fileHidden = false
}
} else {
fmt.Println(UI_FileNotFound, _containerFile)
fileHidden = false
}
} else {
fmt.Print(fmt.Sprintf(UI_ParameterInvalid, GetFunctionName()))
fmt.Println(fmt.Sprintf(UI_Parameter, "_containerFile: "+_containerFile+"_hideFile: "+_hideFile))
fileHidden = false
}
return fileHidden
}
// WriteHiddenFileData: Writes the hidden file data to the container file
func WriteHiddenFileData(_containerFile *os.File, _filename string, _steps int64, _spacing int64) bool {
var hiddenFileData HiddenFileData
var filenameNoPath string
var containerFileSize int64 = -1
var seekOffset int64 = -1
var dataWritten = false
var writeContainerFileSize []byte
const WRITE_CONTAINER_FILE_SIZE_BUFFER int = 8
var bytesWritten int = -1
var err error
if _containerFile != nil && len(_filename) > 0 && _steps != -1 && _spacing != -1 {
if len(_filename) > FILENAME_LENGTH {
fmt.Println(fmt.Sprintf(UI_FileNameTooLong, _filename, FILENAME_LENGTH))
dataWritten = false
} else {
// Set up hidden file data structure to write to container file
hiddenFileData = HiddenFileData{}
hiddenFileData.magicNumber = MAGIC_NUMBER
filenameNoPath = filepath.Base(_filename)
copy(hiddenFileData.fileName[:], filenameNoPath)
hiddenFileData.steps = _steps
hiddenFileData.spacing = _spacing
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_HiddenFileData, hiddenFileData.spacing, hiddenFileData.steps, hiddenFileData.fileName))
}
// Get size of container file
containerFileSize = GetFileSize(_containerFile.Name())
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_FileSize, _containerFile.Name(), containerFileSize))
}
if containerFileSize == -1 {
fmt.Println(fmt.Sprintf(UI_NoFileSize, _containerFile.Name(), ""))
dataWritten = false
} else {
// Seek to end of container file
seekOffset, err = _containerFile.Seek(containerFileSize, 0)
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_SeekOffset, seekOffset))
}
if err != nil {
fmt.Println(fmt.Sprintf(UI_SeekFail, _containerFile.Name(), seekOffset, err))
dataWritten = false
} else {
// Write hidden file data to end of container file
err = binary.Write(_containerFile, binary.LittleEndian, hiddenFileData)
if err != nil {
fmt.Println(fmt.Sprintf(UI_FileWriteError, _containerFile.Name(), err))
dataWritten = false
} else {
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_HiddenDataWrittenOK, _filename, _containerFile.Name()))
}
dataWritten = true
}
}
}
if dataWritten == true {
// Write location of hidden file data in container file to fixed offset in container file
writeContainerFileSize = make([]byte, WRITE_CONTAINER_FILE_SIZE_BUFFER)
if len(writeContainerFileSize) != WRITE_CONTAINER_FILE_SIZE_BUFFER {
fmt.Println(UI_NoBufferMemory)
dataWritten = false
} else {
binary.BigEndian.PutUint64(writeContainerFileSize, uint64(containerFileSize))
bytesWritten, err = _containerFile.WriteAt(writeContainerFileSize, HIDDEN_FILE_DATA_OFFSET)
if err != nil {
fmt.Println(fmt.Sprintf(UI_FileWriteError, _containerFile.Name(), ""))
dataWritten = false
} else {
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_BytesWritten, bytesWritten))
}
if bytesWritten != WRITE_CONTAINER_FILE_SIZE_BUFFER {
fmt.Println(fmt.Sprintf(UI_FileWriteError, _containerFile.Name(), ""))
dataWritten = false
} else {
if DEBUG == true {
fmt.Println(fmt.Sprintf(UI_HiddenDataWrittenOK, _filename, _containerFile.Name()))
}
dataWritten = true
}
}
}
}
}
} else {
fmt.Print(fmt.Sprintf(UI_ParameterInvalid, GetFunctionName()))
fmt.Println(fmt.Sprintf(UI_Parameter, "containerFile: "+_containerFile.Name()+"filename: "+_filename+"steps: "+strconv.FormatInt(_steps, 10)+"spacing:"+strconv.FormatInt(_spacing, 10)))
}
return dataWritten
}