-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2pac.py
More file actions
115 lines (96 loc) · 4.28 KB
/
Copy path2pac.py
File metadata and controls
115 lines (96 loc) · 4.28 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
#!/usr/bin/env python3
"""
2PAC — Steganography Tool
Hide secret data inside images. Extract hidden data from images.
Usage:
python 2pac.py hide --image photo.png --data "secret message" --output out.png
python 2pac.py extract --image out.png --password hunter2
"""
import argparse
import os
import sys
from steg_embedder import StegEmbedder
from dct_steg import DctStegEmbedder
from rdh_embedder import RdhEmbedder
def cmd_hide(args):
output = args.output or os.path.splitext(args.image)[0] + '_stego.png'
if args.rdh:
embedder = RdhEmbedder()
success, msg, stats = embedder.embed_data(
args.image, args.data, output, password=args.password
)
elif args.dct:
print("WARNING: DCT mode is non-functional — extraction does not reliably roundtrip.")
print(" Use LSB (default) for reliable embedding. Proceeding anyway...\n")
embedder = DctStegEmbedder(quality=args.quality)
success, msg, stats = embedder.embed_data(
args.image, args.data, output, password=args.password
)
else:
embedder = StegEmbedder()
success, msg, stats = embedder.embed_data(
args.image, args.data, output,
password=args.password,
bits_per_channel=args.bits,
scatter=args.scatter
)
print(msg)
if success:
print(f"Output: {output}")
print(f"Stats: {stats}")
return 0 if success else 1
def cmd_extract(args):
if args.rdh:
embedder = RdhEmbedder()
restore = getattr(args, 'restore', None)
success, msg, data = embedder.extract_data(
args.image, password=args.password, restore_path=restore
)
elif args.dct:
print("WARNING: DCT mode is non-functional — extraction does not reliably roundtrip.\n")
embedder = DctStegEmbedder()
success, msg, data = embedder.extract_data(
args.image, password=args.password
)
else:
embedder = StegEmbedder()
success, msg, data = embedder.extract_data(
args.image, password=args.password,
bits_per_channel=args.bits,
scatter=args.scatter
)
print(msg)
if success:
print(data)
return 0 if success else 1
def main():
parser = argparse.ArgumentParser(
prog='2pac',
description='2PAC — Hide data inside images, or extract hidden data.',
)
sub = parser.add_subparsers(dest='command', required=True)
p_hide = sub.add_parser('hide', help='Hide data inside an image')
p_hide.add_argument('--image', required=True, help='Input image path')
p_hide.add_argument('--data', required=True, help='Text to hide')
p_hide.add_argument('--output', help='Output path (default: <input>_stego.png)')
p_hide.add_argument('--password', help='Encryption password')
p_hide.add_argument('--dct', action='store_true', help='Use DCT (experimental, lower capacity)')
p_hide.add_argument('--bits', type=int, default=1, help='LSB bits per channel 1-4 (default: 1)')
p_hide.add_argument('--quality', type=int, default=95, help='DCT quality (default: 95)')
p_hide.add_argument('--scatter', action='store_true', help='Scatter bits across non-sequential pixels (harder to detect)')
p_hide.add_argument('--rdh', action='store_true', help='Use reversible data hiding (lossless, lower capacity)')
p_ext = sub.add_parser('extract', help='Extract hidden data from an image')
p_ext.add_argument('--image', required=True, help='Image to extract from')
p_ext.add_argument('--password', help='Decryption password')
p_ext.add_argument('--dct', action='store_true', help='DCT extraction (default: LSB)')
p_ext.add_argument('--bits', type=int, default=1, help='LSB bits per channel (default: 1)')
p_ext.add_argument('--scatter', action='store_true', help='Use scattered pixel order (must match embedding)')
p_ext.add_argument('--rdh', action='store_true', help='Extract from reversible data hiding image')
p_ext.add_argument('--restore', help='Save restored original image to this path (RDH only)')
args = parser.parse_args()
if args.command == 'hide':
return cmd_hide(args)
elif args.command == 'extract':
return cmd_extract(args)
if __name__ == '__main__':
sys.exit(main())