let's suppose I have the following possible values of a string:
exp="110"
exp="110-120"
exp="110-120-211"
actually, this is a GET parameter obtained from the URL. exp
can become very large so I want to make it shorter(encrypt it). Not because of security reasons, but because I don't want it to be long and ugly.
So I want to encrypt exp
to become a short string with a fixed length of let's say 15. Is it possible somehow? Something like this:
encrypt("110") results in "Ax1234B"
encrypt("110-120") results in "85xHdjX"
I am using python btw
EDIT
forgot to mention: I also need a decrypt
function to be available. Moreover, I would prefer solutions from the standard python library without having to install new packages.
How long are your strings getting? If they're sufficiently long, you could compress them using zlib
(or another compression module in the standard libary) and then run base64 on it.
>>> z = base64.encodestring(zlib.compress("123"))
>>> print z
eJwzNDIGAAEtAJc=
>>> zlib.decompress(base64.decodestring(z))
'123'
This isn't going to shrink your strings unless they're pretty long, though (in my tests about 36 characters in the original string). You're also not getting a fixed length, but I don't believe there's any way to achieve that.
If you want to convert urls into a fixed length strings; you could use a hash function and a database to be able to retrieve the url given its hash:
import base64
import hashlib
import sqlite3
db = sqlite3.connect('urls.sqlite3')
db.execute('''CREATE TABLE IF NOT EXISTS urls
(hash BLOB PRIMARY KEY, url TEXT)''')
def shorten(url):
h = sqlite3.Binary(hashlib.sha256(url.encode('ascii')).digest())
with db:
db.execute('INSERT OR IGNORE INTO urls VALUES (?, ?)', (h, url))
return base64.urlsafe_b64encode(h).decode('ascii')
def geturl(shortened_url):
h = sqlite3.Binary(base64.urlsafe_b64decode(shortened_url.encode('ascii')))
with db:
url = db.execute('SELECT url FROM urls WHERE hash=?', (h,)).fetchone()
if url is None:
raise KeyError(shortened_url)
return url[0]
urls = ["110", "110-120", "110-120-211"]
width = max(map(len, urls))
for url in urls:
slug = shorten(url)
assert url == geturl(slug)
print('{url:{width}} -> {slug}'.format(**vars()))
110 -> m9sq9nmSBKKZxgOZS45ADksf1iXv23QGbMhp_uQsnfM=
110-120 -> aKGvjidWggSkQ1wBnZoi5f67KlUS1pvoVyhX8Rd04P0=
110-120-211 -> C8LD7lCh5Tm8XCoWJep9OAfSnMikLU5lgQChe-wfQho=
The output always has the same length however long (or short) input urls are.
For a sufficiently long hash with a good algorithm the probability of collision (different urls producing the same hash) is very low for any practical number of url hashes generated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With