-
Notifications
You must be signed in to change notification settings - Fork 7
/
decrypt.py
124 lines (103 loc) · 3.08 KB
/
decrypt.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
#!/usr/bin/python3
from Crypto.Cipher import AES
import hashlib
import hmac
import base64
import sys
appInfo = {
"image": b"WhatsApp Image Keys",
"video": b"WhatsApp Video Keys",
"audio": b"WhatsApp Audio Keys",
"document": b"WhatsApp Document Keys",
"image/webp": b"WhatsApp Image Keys",
"image/jpeg": b"WhatsApp Image Keys",
"image/png": b"WhatsApp Image Keys",
"video/mp4": b"WhatsApp Video Keys",
"audio/aac": b"WhatsApp Audio Keys",
"audio/ogg": b"WhatsApp Audio Keys",
"audio/wav": b"WhatsApp Audio Keys",
}
extension = {
"image": "jpg",
"video": "mp4",
"audio": "ogg",
"document": "bin",
}
def HKDF(key, length, appInfo=b""):
key = hmac.new(b"\0"*32, key, hashlib.sha256).digest()
keyStream = b""
keyBlock = b""
blockIndex = 1
while len(keyStream) < length:
keyBlock = hmac.new(
key,
msg=keyBlock+appInfo + (chr(blockIndex).encode("utf-8")),
digestmod=hashlib.sha256).digest()
blockIndex += 1
keyStream += keyBlock
return keyStream[:length]
def AESUnpad(s):
return s[:-ord(s[len(s)-1:])]
def AESDecrypt(key, ciphertext, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)
return AESUnpad(plaintext)
def decrypt(fileName, mediaKey, mediaType, output):
mediaKeyExpanded = HKDF(mediaKey, 112, appInfo[mediaType])
macKey = mediaKeyExpanded[48:80]
mediaData = open(fileName, "rb").read()
file = mediaData[:-10]
mac = mediaData[-10:]
data = AESDecrypt(mediaKeyExpanded[16:48], file, mediaKeyExpanded[:16])
if output is None:
if "/" in mediaType:
fileExtension = mediaType.split("/")[1]
else:
fileExtension = extension[mediaType]
output = fileName.replace('.enc', '.{}'.format(fileExtension))
with open(output, 'wb') as f:
f.write(data)
return True
if __name__ == "__main__":
from optparse import OptionParser
parser = OptionParser(version='1')
parser.add_option(
'-m',
'--mime',
dest='mediaType',
default='image',
help="media type of the encrypted file. Default 'image'"
)
parser.add_option(
'-b',
'--base64',
dest='base64Key',
default=None,
help='media key in Base64'
)
parser.add_option(
'-j',
'--hex',
dest='hexKey',
default=None,
help='media key in Hex'
)
parser.add_option(
'-o',
'--output',
dest='output',
default=None,
help='path for the plaintext'
)
(options, args) = parser.parse_args()
fileName = args[0]
if options.base64Key is not None:
mediaKey = base64.b64decode(options.base64Key)
elif options.hexKey is not None:
mediaKey = bytes.fromhex(options.hexKey)
else:
print("You must specify the key in either "
"Base64 or Hex.\nUsage: decrypt.py -h")
sys.exit(1)
if decrypt(fileName, mediaKey, options.mediaType, options.output):
print("Decrypted (hopefully)")