-
Notifications
You must be signed in to change notification settings - Fork 3
/
zero-width-steganography.py
139 lines (106 loc) · 3.84 KB
/
zero-width-steganography.py
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
import argparse
import zerowidth
def check_args(args: argparse.Namespace) -> bool:
if args.clear_source and args.file_source:
print("Invalid options. Pass either a string source or a file source.")
return False
if [args.encode, args.decode, args.clean].count(True) != 1:
print("Invalid options. Pass either encode, decode or clear.")
return False
if not (args.clear_source or args.file_source) and args.encode:
print("Invalid options. Pass one source.")
return False
if not args.to_hide and args.encode:
print("Invalid options. Pass a string to hide.")
return False
if args.encode:
if not args.position:
args.position = zerowidth.Position.NTHLINES
else:
try:
args.position = zerowidth.Position(int(args.position))
except ValueError:
print("Invalid position.")
return False
try:
args.k = int(args.k)
except ValueError:
print("Invalid k.")
return False
return True
def clean(args: argparse.Namespace):
z = zerowidth.ZeroWidth()
if args.file_source:
cleaned = z.cleanFile(source_path=args.file_source)
else:
cleaned = z.clean(source=args.clear_source)
if args.output_path:
with open(args.output_path, "w") as f:
f.write(cleaned)
return
print(cleaned)
def encode(args: argparse.Namespace):
z = zerowidth.ZeroWidth()
clear = args.to_hide
if args.file_source:
encoded = z.zeroEncodeFile(
source_path=args.file_source, clear=clear, position=args.position, k=args.k
)
else:
encoded = z.zeroEncode(
clear=clear, source=args.clear_source, position=args.position, k=args.k
)
if args.output_path:
with open(args.output_path, "w") as f:
f.write(encoded)
return
print(encoded)
def decode(args: argparse.Namespace):
z = zerowidth.ZeroWidth()
if args.file_source:
decoded = z.zeroDecodeFile(source_path=args.file_source)
else:
decoded = z.zeroDecode(source=args.clear_source)
if args.output_path:
with open(args.output_path, "w") as f:
f.write(decoded)
return
print(decoded)
def main():
parser = argparse.ArgumentParser(
description="Hide and recover text in plainsight",
)
parser.add_argument("-V", "--version", help="library version", action="store_true")
parser.add_argument("-E", "--encode", help="encode text", action="store_true")
parser.add_argument("-D", "--decode", help="decode text", action="store_true")
parser.add_argument("-C", "--clean", help="clear file", action="store_true")
parser.add_argument("-t", "--to-hide", help="string to encode")
parser.add_argument("-f", "--file-source", help="file source")
parser.add_argument("-c", "--clear-source", help="clear string")
parser.add_argument("-o", "--output-path", help="output path")
parser.add_argument(
"-p",
"--position",
help="hidden string position. 0 for TOP, 1 for BOTTOM, 2 for RANDOM, "
"3 for NTHLINES, 4 for RANDOMINLINE",
default=3,
)
parser.add_argument("-k", "-position-k", help="position variator", default=1)
args = parser.parse_args()
if not check_args(args):
return
if args.version:
z = zerowidth.ZeroWidth()
print(f"Zero width version: {z.version}")
return
if args.clean:
clean(args)
return
if args.encode:
encode(args)
return
if args.decode:
decode(args)
return
if __name__ == "__main__":
main()