-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStegAudLib.py
122 lines (99 loc) · 3.51 KB
/
StegAudLib.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
import wave
import numpy as np
import pyaudio
import binascii
import sys
import os
import shutil
from time import sleep
class SteganographyAudioException(Exception):
pass
class StegAud():
def __init__(self):
pass
def text2bin(self, text):
binary = ''.join(format(ord(x), 'b').zfill(8) for x in text)
return binary
#turn binary to ASCII text
def bin2text(self, bin):
a = int(bin, 2)
hex_string = '%x' % a
n = len(hex_string)
z = binascii.unhexlify(hex_string.zfill(n + (n & 1)))
text=z.decode('ascii')
return text
def encode(self, audioFile, message):
wr = wave.open(str(audioFile), 'r')
# Set the parameters for the output file.
par = list(wr.getparams())
par[3] = 0 # The number of samples will be set by writeframes.
par = tuple(par)
newFilename = str(audioFile)[:-4] + "_encoded.wav"
ww = wave.open(newFilename, 'w')
ww.setparams(par)
fr = 20
sz = wr.getframerate()//fr # Read and process 1/fr second at a time.
# A larger number for fr means less reverb.
c = int(wr.getnframes()/sz) # count of the whole file
binMessage = self.text2bin(str(message))
binLength = self.text2bin(str(len(binMessage)))
count = 0
#Check if audio file is long enough to encode message
if(c < len(binMessage) + 32):
print("Audio file not large enough for message")
exit()
#Encoding 0's to fill in the rest of the 32 bits that are for length
for i in range(32 - len(binLength)):
da = np.fromstring(wr.readframes(sz), dtype=np.int32)
b = self.text2bin(str(da[0]))
b = b[:len(b) -1] + '0'
B = self.bin2text(b)
da[0] = int(B)
ww.writeframes(da.tostring())
#Encoding the length
for i in binLength:
da = np.fromstring(wr.readframes(sz), dtype=np.int32)
b = self.text2bin(str(da[0]))
b = b[:len(b) -1] + i
B = self.bin2text(b)
da[0] = int(B)
ww.writeframes(da.tostring())
#Encoding the message
for i in binMessage:
da = np.fromstring(wr.readframes(sz), dtype=np.int32)
b = self.text2bin(str(da[0]))
b = b[:len(b) -1] + i
B = self.bin2text(b)
da[0] = int(B)
ww.writeframes(da.tostring())
#Finishing the rest of the audio file
for i in range(c - 32 - len(binMessage)):
da = np.fromstring(wr.readframes(sz), dtype=np.int32)
ww.writeframes(da.tostring())
wr.close()
ww.close()
filename = str(os.path.basename(str(audioFile)))
os.remove(str(audioFile))
shutil.move(newFilename, str(audioFile))
def decode(self, audioFile):
wr = wave.open(str(audioFile), 'r')
fr = 20
sz = wr.getframerate()//fr # Read and process 1/fr second at a time.
c = int(wr.getnframes()/sz) # count of the whole file
length = ""
#Get the length of the message
for i in range(32):
da = np.fromstring(wr.readframes(sz), dtype=np.int32)
b = self.text2bin(str(da[0]))
length += b[-1:]
length = int(self.bin2text(length))
#Decode the message
message = ""
for i in range(length):
da = np.fromstring(wr.readframes(sz), dtype=np.int32)
b = self.text2bin(str(da[0]))
message += b[-1:]
#Change message from binary to text
message = self.bin2text(message)
wr.close()
return message;