· 6 years ago · Aug 15, 2019, 11:10 AM
1#!/usr/bin/python3
2
3import webapp2
4import logging
5from urllib.parse import urlparse
6from paste import httpserver
7import sys
8from Crypto.Cipher import PKCS1_OAEP
9from Crypto.PublicKey import RSA
10from Crypto.Cipher import AES
11import ksm
12import base64
13from hashlib import md5, sha1
14import json
15import sys
16from keygen import KeyManager
17
18globalConfig = {}
19Key = bytes([0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C])
20IV = bytes([0xD5,0xFB,0xD6,0xB8,0x2E,0xD9,0x3E,0x4E,0xF9,0x8A,0xE4,0x09,0x31,0xEE,0x33,0xB7])
21
22"""Setup Console Logging."""
23_LOG = logging.getLogger("proxy")
24_LOG.setLevel(logging.DEBUG)
25consoleHandler = logging.StreamHandler()
26consoleHandler.setLevel(logging.DEBUG)
27formatter = logging.Formatter(
28 '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
29consoleHandler.setFormatter(formatter)
30_LOG.addHandler(consoleHandler)
31
32try:
33 with open('./config.json', 'r') as f:
34 globalConfig = json.loads(f.read())
35except IOError as e:
36 _LOG.error('error reading config file: %s', e.message)
37 sys.exit(1)
38except json.decoder.JSONDecodeError as e:
39 _LOG.error('error parsing JSON file: %s', e)
40 sys.exit(2)
41
42try:
43 secretKey = globalConfig['secretKey']
44 secretIv = globalConfig['secretIV']
45 aKeyFile = globalConfig['fpsCertFile']
46 certFile = globalConfig['fpsCertKeyFile']
47 listenIp = globalConfig['listenIp']
48 useDbs = globalConfig['useDbs']
49 dbType = globalConfig['dbs'][useDbs[0]]['type']
50 dbIP = globalConfig['dbs'][useDbs[0]]['ipaddress']
51 dbUser = globalConfig['dbs'][useDbs[0]]['user']
52 dbPass = globalConfig['dbs'][useDbs[0]]['pass']
53 dbSchema = globalConfig['dbs'][useDbs[0]]['schema']
54except KeyError as k:
55 print("Parameter", k , "not found")
56 sys.exit(3)
57
58
59def decryptSPCK(payload, keyFile):
60 key = RSA.importKey(open(keyFile).read())
61 cipher = PKCS1_OAEP.new(key)
62 message = cipher.decrypt(payload)
63 return message
64
65def decryptPayload(payload, key, iv):
66 cipher = AES.new(key, AES.MODE_CBC, iv)
67 return cipher.decrypt(payload)
68
69def parseSpc(data):
70 spc = {}
71 spc['version'] = data[0:4]
72 spc['IV'] = data[8:24]
73 spc['encrKey'] = data[24:152]
74 spc['key'] = decryptSPCK(spc['encrKey'], aKeyFile)
75 spc['certHash'] = data[152:172]
76 spc['payloadLen'] = data[172:176]
77 # spc['payloadEncr'] = data[176:]
78 spc['payload'] = decryptPayload(data[176:], spc['key'], spc['IV'])
79
80 aKsm = ksm.ksm(spc['payload'])
81 Key = bytes([0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C])
82 IV = bytes([0xD5,0xFB,0xD6,0xB8,0x2E,0xD9,0x3E,0x4E,0xF9,0x8A,0xE4,0x09,0x31,0xEE,0x33,0xB7])
83 if not aKsm.getError():
84 _LOG.info('scp had been parsed successfully')
85 _LOG.info('returning back CKC')
86 return aKsm.generateCKC(Key, IV)
87 else:
88 _LOG.error(aKsm.getError())
89 return aKsm.getError()
90
91def decodeHash(aHash, key, iv):
92 try:
93 cipher = AES.new(key, AES.MODE_CBC, iv)
94 ret = cipher.decrypt(aHash)
95 _LOG.debug(ret.hex())
96 return ret[0:20]
97 except:
98 return -1
99
100def getKeyEncrypted(contentId, random1):
101 #TODO get real key
102 value = contentId.decode('UTF-8')
103 result = init.getkey(value)
104 if(result[1] == False):
105 Key = result[0][1]
106 IV = result[0][2]
107 else:
108 Key = result[0][0][1]
109 IV = result[0][0][2]
110
111 try:
112 cipher = AES.new(int(secretKey, 16).to_bytes(16, byteorder='big'), AES.MODE_CBC, int(secretIv, 16).to_bytes(16, byteorder='big'))
113 keyIvRandom = Key + IV + random1
114 return cipher.encrypt(keyIvRandom)
115 except:
116 return -1
117
118class proxyHandler(webapp2.RequestHandler):
119 def post(self):
120 """Handles HTTP Posts sent to the proxy."""
121 self.debug_info = ""
122 _LOG.info(dir(self.request))
123 _LOG.info(self.request.query)
124 if self.request.body is None:
125 _LOG.debug("Empty Request")
126 return None
127 _LOG.info(self.request.content_length)
128 if self.request.content_length > 100:
129 response = parseSpc(self.request.body)
130 self.response.write(base64.b64encode(response))
131
132 def get(self):
133 """Handles HTTP Gets sent to the proxy."""
134 self.debug_info = None
135 self.send400("GET Not Supported")
136
137 def send400(self, text):
138 """Send 400 Error Response"""
139 self.response.status = 400
140 self.response.write(self.response.write(text))
141
142 def send500(self, text):
143 """Send 500 Error Response"""
144 self.response.status = 500
145 self.response.write(self.response.write(text))
146
147class getKey(webapp2.RequestHandler):
148
149 def post(self):
150 self.debug_info = ""
151 if self.request.body is None:
152 _LOG.debug("Empty Request")
153 return None
154 _LOG.info(self.request.content_length)
155 _LOG.info('Handling GetKey request')
156 try:
157 print(self.request.body)
158 jsonData = json.loads(self.request.body)
159 # if ('contentId', 'hash', 'random') in jsonData.keys():
160 if all(j in jsonData for j in ['contentId', 'hash', 'random']):
161 clearHash = decodeHash(base64.b64decode(jsonData['hash']), int(secretKey, 16).to_bytes(16, byteorder='big'), int(secretIv, 16).to_bytes(16, byteorder='big'))
162 # clearHash = decodeHash(base64.b64decode(jsonData['hash']), Key, IV)
163 aRandom = base64.b64decode(jsonData['random'])
164
165 if clearHash == -1:
166 self.send400('invalid request1')
167 return None
168 sha = sha1()
169 sha.update(bytes(base64.b64decode(jsonData['contentId'])))
170 _LOG.debug('clear: ' + clearHash.hex() + ' local ' + sha.digest().hex())
171 if clearHash != sha.digest():
172 _LOG.info('bad request. hash missmatch')
173 self.send400('invalid request2')
174 return None
175 else:
176 response = base64.b64encode(getKeyEncrypted(base64.b64decode(jsonData['contentId']), aRandom))
177 self.response.write(response)
178 else:
179 self.send400('invalid request3')
180 except json.decoder.JSONDecodeError:
181 self.send400('invalid request4')
182
183 def get(self):
184 """Handles HTTP Gets sent to the proxy."""
185 self.debug_info = None
186 self.send400("GET Not Supported")
187
188 def send400(self, text):
189 """Send 400 Error Response"""
190 self.response.status = 400
191 self.response.write(self.response.write(text))
192
193 def send500(self, text):
194 """Send 500 Error Response"""
195 self.response.status = 500
196 self.response.write(self.response.write(text))
197
198
199app = webapp2.WSGIApplication([('/', proxyHandler),('/getkey', getKey)], debug=True)
200init = KeyManager(dbIP,dbUser,dbPass,dbSchema)
201
202def main():
203 httpserver.serve(app, host=listenIp, port='8888')
204
205if __name__ == '__main__':
206 main()