forked from fbngrm/Matroschka
/
matroschka.py
185 lines (148 loc) · 5.45 KB
/
matroschka.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
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
import Image
import argparse
import hashlib
import hmac
import os
import steganohide as stg
import xtea
import sys
def create_hmac(mac_pass, msg_bytes):
"""
Create an hmac keyed hash for the given message
using the SHA-256 digest algorithm.
"""
return hmac.new(
mac_pass, msg_bytes, digestmod=hashlib.sha256).digest()
def get_msg(img):
"""
Extract the hidden message fro the given image.
Authenticate the hidden message by validating the
hmac hash sliced from the hidden message.
"""
i = Image.open('%s.ste' % img)
secret = stg.extract_msg(i)
mac = secret.split('--:--')[0]
print 'HMAC hex is: \n%s\n' % mac.encode('hex')
data = secret.split('--:--')[1]
print 'The hidden message is: \n%s\n' % data
check_hmac(mac)
i.show()
def check_hmac(mac, data):
"""
Check if the given hmac ist valid by creating
a new hmac with the supplied password and the data.
"""
h_mac = hmac.new(args['m'], bytes(data), digestmod=hashlib.sha256).digest()
print 'HMAC validation: \n%s\n' % str(h_mac == mac)
def hash_128_bit_pass(passwd):
"""
Create a hash of the given password using the
SHA-256 digest algorithm.
"""
h = hashlib.sha256()
h.update(passwd)
return h.hexdigest()[:16]
def crypt(key, data, iv):
"""
Encrypt or decrypt the given data with the given
key using the XTEA algorithm in CFB mode.
"""
return xtea.crypt(key, data, iv)
def read_image(image_path):
"""
Read the image data of the given path
and return an Image object
"""
if not os.path.exists(image_path):
raise IOError('File does not exist: %s' % image_path)
else:
return Image.open(image_path)
def read_text(text_path):
"""
Read the content of the given text file and
return the content as a string
"""
if not os.path.exists(text_path):
raise IOError('File does not exist: %s' % text_path)
return open(text_path).read()
def encrypt(data_type):
# create hmac from the supplied mac password hashed with SHA-256
# digest algorithm and the supllied image or text data
h_mac = create_hmac(args['m'], bytes(data))
# join hmac and message data
secret = '%s--:--%s' % (h_mac, data)
# create a SHA-256 hash of the high-order 128 bit of the given password
key = hash_128_bit_pass(args['k'])
# encrypt the data using XTEA algorithm in CFB mode with the 128 bit
# SHA-256 hash of the password as key and a random seed of 8 bytes
iv = os.urandom(8)
encrypted_secret = crypt(key, secret, iv)
# prepend the iv to the encrypted data because it is required for
# the decryption and hide the data in the image
matroschka = stg.hide_msg(image, '%s--:--%s--:--%s' % (
data_type, iv, encrypted_secret))
# save the image containing the embeded and encrypted
# data to disk with the extension .ste
matroschka.save(args['image'])
print "successfully encrypted your secret message"
matroschka.show()
def decrypt():
# extract and authenticate the hidden message in the image data
image = Image.open(args['image'])
matroschka = stg.extract_msg(image)
# get the 8 byte iv and the encrypted secret from the image data
data_type, iv, encrypted_secret = matroschka.split('--:--')
# create a SHA-256 hash of the high-order 128 bit of the given password
key = hash_128_bit_pass(args['k'])
# decrypt the secret with the iv and the supplied password
decrypted_secret = crypt(key, encrypted_secret, iv)
# split hmac and message data
mac, data = decrypted_secret.split('--:--')
if data_type == 'image':
ipath = "resources/secret-image.png"
print "the secret image is stored under: " + ipath
fh = open(ipath, "wb")
fh.write(data.decode('base64'))
fh.close()
Image.open(ipath).show()
else:
print 'The hidden message is: \n%s\n' % data
print 'HMAC hex is: \n%s\n' % mac.encode('hex')
check_hmac(mac, data)
if __name__ == '__main__':
# Add the command-line arguments
parser = argparse.ArgumentParser(description='Description of your program')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-hide', help='encrypt', action='store_true')
group.add_argument('-open', help='decrypt', action='store_true')
parser.add_argument(
'-m', metavar='macpasswd', help='macpassword', required=True)
parser.add_argument('-k', metavar='passwd', help='password', required=True)
parser.add_argument('data', nargs='?')
parser.add_argument('image')
args = vars(parser.parse_args())
# Check if the required args are supplied
# If not print user feedback and exit
if args['data']:
if args['data'].endswith('png') or args['data'].endswith('jpg'):
import base64
data_type = 'image'
with open(args['data'], "rb") as imageFile:
data = base64.b64encode(imageFile.read())
elif args['data'].endswith('txt'):
data_type = 'text'
data = read_text(args['data'])
else:
print "need secret message either as .txt or .png file"
sys.exit(0)
if args['image']:
image = read_image(args['image'])
else:
print "need image to embed data"
sys.exit(0)
# encrypt the secret message
if args['hide']:
encrypt(data_type)
# decrypt the secret message
if args['open']:
decrypt()