4141from urllib .parse import urlencode , parse_qs
4242import requests
4343from Cryptodome .Cipher import AES
44- from Cryptodome .Hash import SHA
44+ from Cryptodome .Hash import SHA256
4545from Cryptodome import Random
4646import time
4747
@@ -75,15 +75,19 @@ def login(request):
7575 s = "t=%s&%s" % (int (time .time ()), urlencode ({'r' : request .GET ['next' ]}))
7676 # Now encrypt it
7777 r = Random .new ()
78- iv = r .read (16 )
79- encryptor = AES .new (SHA .new (settings .SECRET_KEY .encode ('ascii' )).digest ()[:16 ], AES .MODE_CBC , iv )
80- cipher = encryptor .encrypt (s .encode ('ascii' ) + b' ' * (16 - (len (s ) % 16 ))) # pad to 16 bytes
81-
82- return HttpResponseRedirect ("%s?d=%s$%s" % (
83- settings .PGAUTH_REDIRECT ,
84- base64 .b64encode (iv , b"-_" ).decode ('utf8' ),
85- base64 .b64encode (cipher , b"-_" ).decode ('utf8' ),
86- ))
78+ nonce = r .read (16 )
79+ encryptor = AES .new (
80+ SHA256 .new (settings .SECRET_KEY .encode ('ascii' )).digest ()[:32 ], AES .MODE_SIV , nonce = nonce
81+ )
82+ cipher , tag = encryptor .encrypt_and_digest (s .encode ('ascii' ))
83+
84+ return HttpResponseRedirect ("%s?%s" % (settings .PGAUTH_REDIRECT , urlencode ({
85+ 'd' : '$' .join ((
86+ base64 .b64encode (nonce , b"-_" ).decode ('utf8' ),
87+ base64 .b64encode (cipher , b"-_" ).decode ('utf8' ),
88+ base64 .b64encode (tag , b"-_" ).decode ('utf8' ),
89+ )),
90+ })))
8791 else :
8892 return HttpResponseRedirect (settings .PGAUTH_REDIRECT )
8993
@@ -103,17 +107,24 @@ def auth_receive(request):
103107 # This was a logout request
104108 return HttpResponseRedirect ('/' )
105109
106- if 'i ' not in request .GET :
107- return HttpResponse ("Missing IV in url!" , status = 400 )
110+ if 'n ' not in request .GET :
111+ return HttpResponse ("Missing nonce in url!" , status = 400 )
108112 if 'd' not in request .GET :
109113 return HttpResponse ("Missing data in url!" , status = 400 )
114+ if 't' not in request .GET :
115+ return HttpResponse ("Missing tag in url!" , status = 400 )
110116
111117 # Set up an AES object and decrypt the data we received
112118 try :
113- decryptor = AES .new (base64 .b64decode (settings .PGAUTH_KEY ),
114- AES .MODE_CBC ,
115- base64 .b64decode (str (request .GET ['i' ]), "-_" ))
116- s = decryptor .decrypt (base64 .b64decode (str (request .GET ['d' ]), "-_" )).rstrip (b' ' ).decode ('utf8' )
119+ decryptor = AES .new (
120+ base64 .b64decode (settings .PGAUTH_KEY ),
121+ AES .MODE_SIV ,
122+ nonce = base64 .b64decode (str (request .GET ['n' ]), "-_" ),
123+ )
124+ s = decryptor .decrypt_and_verify (
125+ base64 .b64decode (str (request .GET ['d' ]), "-_" ),
126+ base64 .b64decode (str (request .GET ['t' ]), "-_" ),
127+ ).rstrip (b' ' ).decode ('utf8' )
117128 except UnicodeDecodeError :
118129 return HttpResponse ("Badly encoded data found" , 400 )
119130 except Exception :
@@ -200,11 +211,16 @@ def auth_receive(request):
200211 # Finally, check of we have a data package that tells us where to
201212 # redirect the user.
202213 if 'd' in data :
203- (ivs , datas ) = data ['d' ][0 ].split ('$' )
204- decryptor = AES .new (SHA .new (settings .SECRET_KEY .encode ('ascii' )).digest ()[:16 ],
205- AES .MODE_CBC ,
206- base64 .b64decode (ivs , b"-_" ))
207- s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b' ' ).decode ('utf8' )
214+ (nonces , datas , tags ) = data ['d' ][0 ].split ('$' )
215+ decryptor = AES .new (
216+ SHA256 .new (settings .SECRET_KEY .encode ('ascii' )).digest ()[:32 ],
217+ AES .MODE_SIV ,
218+ nonce = base64 .b64decode (nonces , b"-_" ),
219+ )
220+ s = decryptor .decrypt_and_verify (
221+ base64 .b64decode (datas , "-_" ),
222+ base64 .b64decode (tags , "-_" ),
223+ ).rstrip (b' ' ).decode ('utf8' )
208224 try :
209225 rdata = parse_qs (s , strict_parsing = True )
210226 except ValueError :
@@ -304,17 +320,24 @@ def user_search(searchterm=None, userid=None):
304320 r = requests .get (
305321 '{0}search/' .format (settings .PGAUTH_REDIRECT ),
306322 params = q ,
323+ timeout = 10 ,
307324 )
308325 if r .status_code != 200 :
309326 return []
310327
311- (ivs , datas ) = r .text .encode ('utf8' ).split (b'&' )
328+ (nonces , datas , tags ) = r .text .encode ('utf8' ).split (b'&' )
312329
313330 # Decryption time
314- decryptor = AES .new (base64 .b64decode (settings .PGAUTH_KEY ),
315- AES .MODE_CBC ,
316- base64 .b64decode (ivs , "-_" ))
317- s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b' ' ).decode ('utf8' )
331+ decryptor = AES .new (
332+ base64 .b64decode (settings .PGAUTH_KEY ),
333+ AES .MODE_SIV ,
334+ nonce = base64 .b64decode (nonces , "-_" )
335+ )
336+ s = decryptor .decrypt_and_verify (
337+ base64 .b64decode (datas , "-_" ),
338+ base64 .b64decode (tags , "-_" ),
339+ ).rstrip (b' ' ).decode ('utf8' )
340+
318341 j = json .loads (s )
319342
320343 return j
0 commit comments