Reputation: 1211
There is one same question in StackOverflow with this link: How to generate temporary URLs in Django
But the accepted answer code is for Python 2 and I converted it to Python 3:
import hashlib, zlib
import pickle as pickle
import urllib.request, urllib.parse, urllib.error
my_secret = "michnorts"
def encode_data(data):
"""Turn `data` into a hash and an encoded string, suitable for use with `decode_data`."""
text = zlib.compress(pickle.dumps(data, 0)).encode('base64').replace('\n', '')
m = hashlib.md5(my_secret + text).hexdigest()[:12]
return m, text
def decode_data(hash, enc):
"""The inverse of `encode_data`."""
text = urllib.parse.unquote(enc)
m = hashlib.md5(my_secret + text).hexdigest()[:12]
if m != hash:
raise Exception("Bad hash!")
data = pickle.loads(zlib.decompress(text.decode('base64')))
return data
hash, enc = encode_data(['Hello', 'Goodbye'])
print(hash, enc)
print(decode_data(hash, enc))
But it have error :
text = zlib.compress(pickle.dumps(data, 0)).encode('base64').replace('\n', '')
AttributeError: 'bytes' object has no attribute 'encode'
How should I fix this?
Upvotes: 1
Views: 972
Reputation: 1083
I recommend to use the built-in secrets modules, especially secrets.token_urlsafe.
Upvotes: 0
Reputation: 620
Trying to adapt your code to Python 3, I came up with this:
import hashlib, zlib
import pickle as pickle
import urllib.request, urllib.parse, urllib.error
import base64
my_secret = "michnorts"
def encode_data(data):
"""Turn `data` into a hash and an encoded string, suitable for use with `decode_data`."""
compressed_text = zlib.compress(pickle.dumps(data, 0))
text = base64.b64encode(compressed_text).decode().replace('\n', '')
m = hashlib.md5(str.encode('{}{}'.format(my_secret, text))).hexdigest()[:12]
return m, text
def decode_data(hash, enc):
"""The inverse of `encode_data`."""
text = urllib.parse.unquote(enc)
m = hashlib.md5(str.encode('{}{}'.format(my_secret, text))).hexdigest()[:12]
if m != hash:
raise Exception("Bad hash!")
data = pickle.loads(zlib.decompress(base64.b64decode(text)))
return data
hash, enc = encode_data(['Hello', 'Goodbye'])
print(hash, enc)
print(decode_data(hash, enc))
There are some things that I needed to take into account:
bytes
object into a string, I used the bytes.decode methodbytes
object, I used the str.encode functionhashlib.md5
function accepts a bytes
object (strings need to be previously encoded)str1 + str2
) with a more pythonic construction: '{}{}'.format(str1, str2)
I hope this will be helpful ;)
Upvotes: 4