-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvsteg.py
More file actions
executable file
·171 lines (143 loc) · 5.65 KB
/
vsteg.py
File metadata and controls
executable file
·171 lines (143 loc) · 5.65 KB
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
#!/usr/bin/env python3
import sys, os, argparse
from PIL import Image
from itertools import chain
from steg import get_bits, get_bits_from_file
import skvideo.io
import numpy as np
def get_arg_parser():
parser = argparse.ArgumentParser(
description='Steganographically embed or \
extract information using vessel video files.'
)
general_options = parser.add_argument_group("General Options")
general_options.add_argument(
"-e", "--extract", dest="is_extract",
action="store_true", default=False,
help="Extract data from a vessel video"
)
io_options = parser.add_argument_group("I/O Options")
io_options.add_argument('vessel_video')
io_options.add_argument(
"-i", "--input", dest="input_file",
help="File to embed into the video"
)
io_options.add_argument(
"-o", "--output", dest="output_file",
help="File to output to. If left blank, \
overwrite or save to <inputimage>.uvsl for \
embedding and extracting, respectively"
)
return parser
def get_fake_bits():
ba = [1]*200
for byte in ba:
for i in range(8)[::-1]:
yield (byte & 2**i) >> i
def embed(vessel_video, input_file):
# create a 1-bit-at-a-time generator for the size of the input
size_in_bytes = (os.path.getsize(input_file.name)).to_bytes(8, "big")
size_generator = get_bits(bytearray(size_in_bytes))
# do the same for the input itself
input_generator = get_bits_from_file(input_file)
#chain them together
bits = chain(size_generator, input_generator)
#bits = get_fake_bits()
video_shape = vessel_video.shape
vessel_bytes = bytearray(vessel_video.tobytes())
for i, byte in enumerate(vessel_bytes):
try:
vessel_bytes[i] = (byte & ~4) | (next(bits) << 2)
if i < 64:
print((vessel_bytes[i] & 4)>>2,end="")
# create buffer bits - last two bits must be different
# if 1 is added or subtracted, the 3rd bit won't change
if vessel_bytes[i] & 3 == 0:
vessel_bytes[i] = (byte & ~3) | 1
if vessel_bytes[i] & 3 == 3:
vessel_bytes[i] = (byte & ~3) | 2
except StopIteration:
#print("\t".join(str(b) for b in vessel_bytes[:64]))
size = int.from_bytes(size_in_bytes, "big")
#print(bin(size))
video_array = np.frombuffer(vessel_bytes, np.dtype(np.uint8))
return video_array.reshape(video_shape)
def extract(vessel_video):
vessel_bytes = vessel_video.tobytes()
# retreive the size of the input file from the first 8 bytes
print(type(vessel_bytes[:64]))
#print("\t".join(str(b) for b in vessel_bytes[:64]))
source = vessel_bytes[:64]
target = bytearray(8)
for i, _ in enumerate(target):
for byte in source[i * 8 : (i+1) * 8]:
print(bin(byte), end="\t")
print("\n\n")
size_in_bytes = build_from_bits(8, vessel_bytes[:64])
#print("\t".join(str(b) for b in size_in_bytes[:64]))
size = int.from_bytes(size_in_bytes, "big")
#print(bin(size))
# edge case where an arbitrary file is being read from
if size > sys.maxsize:
message = "Error: target file size too large. \n (Are you sure you're extracting from the right file?)"
raise OverflowError(message)
return 0
#return build_from_bits(size, vessel_bytes[64:])
# constructs target from the 3rd to last bit from each byte in source
def build_from_bits(size_of_target, source):
target = bytearray(size_of_target)
for i, _ in enumerate(target):
for byte in source[i * 8 : (i+1) * 8]:
print(bin(byte), end="\t")
target[i] <<= 1
#if i<64:
#print(bin((byte & 4) >> 2), end="")
target[i] |= (byte & 4) >> 2
#print(" ", bin(target[i]))
#print(" &&&& ", bin(target[i]))
return target
def steg(args):
vessel_video_path = args.vessel_video
vessel_video = skvideo.io.vread(vessel_video_path)
### Embedding ###
if not args.is_extract:
if not args.input_file:
print("Error: No input file provided.")
quit()
input_file_path = args.input_file
if not args.output_file:
print("an output file wasn't provided, the file will be overwritten. \
Continue? (y/n)")
if (input().upper() != "Y"):
quit()
input_size = os.path.getsize(input_file_path)
vessel_size = len(vessel_video.tobytes())
if (vessel_size / 8 < input_size):
print("Error: input is larger than what can be stored")
print("input size: " + str(input_size))
print("vessel size: " + str(int(vessel_size / 8)))
quit()
with open(input_file_path, "rb") as input_file:
vid = embed(vessel_video, input_file)
output_file_path = args.output_file if args.output_file else vessel_video_path
try:
outputdict = dict()
outputdict["-c:v"] = "libx264"
outputdict["-crf"] = "7"
skvideo.io.vwrite(output_file_path, vid, outputdict=outputdict)
except Exception as e:
print(e)
### Extracting ###
else:
output_file_path = args.output_file if args.output_file else vessel_video_path + ".uvsl"
with open(output_file_path, "wb") as output_file:
try:
output_file.write(extract(vessel_video))
except Exception as e:
print(e)
os.remove(output_file_path)
def main():
args = get_arg_parser().parse_args()
steg(args)
if __name__ == '__main__':
main()