Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 加密字符串以获得固定长度_Python_Django_Url_Encoding_Compression - Fatal编程技术网

Python 加密字符串以获得固定长度

Python 加密字符串以获得固定长度,python,django,url,encoding,compression,Python,Django,Url,Encoding,Compression,假设我有以下可能的字符串值: exp="110" exp="110-120" exp="110-120-211" 实际上,这是从URL获得的GET参数exp可能会变得非常大,因此我想将其缩短(加密)。不是因为安全原因,而是因为我不想让它长而难看 所以我想加密exp成为一个固定长度的短字符串,比如说15。有可能吗?大概是这样的: encrypt("110") results in "Ax1234B" encrypt("110-120") results in "85xHdjX" 顺便说

假设我有以下可能的字符串值:

exp="110"
exp="110-120"
exp="110-120-211"
实际上,这是从URL获得的GET参数
exp
可能会变得非常大,因此我想将其缩短(加密)。不是因为安全原因,而是因为我不想让它长而难看

所以我想加密
exp
成为一个固定长度的短字符串,比如说15。有可能吗?大概是这样的:

encrypt("110")     results in "Ax1234B"
encrypt("110-120") results in "85xHdjX"
顺便说一句,我正在使用python

编辑


忘了提到:我还需要一个
解密
函数。此外,我更喜欢标准python库中的解决方案,而不必安装新的软件包。

如果安全性根本不是问题,您只想混淆和缩小,那么可以使用?它是用Javascript和Python实现的,因此您可以轻松地在前端对其进行编码,在后端对其进行解码


但是,这不会得到固定的长度,除非您故意将长度增加到比实际长度大的某个长度。

字符串的长度是多少?如果它们足够长,您可以使用
zlib
(或标准库中的另一个压缩模块)压缩它们,然后在其上运行base64

>>> z = base64.encodestring(zlib.compress("123"))
>>> print z 
eJwzNDIGAAEtAJc=
>>> zlib.decompress(base64.decodestring(z)) 
'123'

但是,这不会缩小字符串,除非它们很长(在我的测试中,原始字符串中大约有36个字符)。你也不能得到一个固定的长度,但我不相信有任何方法可以做到这一点。

不,不可能以可逆的方式将任意大的数据集放入一个固定的长度中。您需要更好地定义要传递的内容

例如,如果:

  • 从您的示例中,它看起来像一个数字列表
  • 这些数字相对较小
  • 不允许复制

如果这些是真的,您可以将列表作为位打包到一个固定大小的二进制流中,最大位数为最大位数,然后进行base64编码。这将是固定长度和可逆的。

如果您想将URL转换为固定长度字符串;您可以使用哈希函数和数据库来检索给定哈希的url:

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]
例子 输出 无论输入URL有多长(或多短),输出总是具有相同的长度


对于具有良好算法的足够长的散列,对于生成的任何实际数量的url散列,冲突的概率(不同的url产生相同的散列)都非常低。

不,不可能以可逆的方式将任意大的数据集放入固定长度。也许你需要重新定义什么是允许的。您当然可以缩短它,因为我们用来缩短的一种方法是压缩字符串,然后对其进行base64编码。这显然不是固定长度,但非常可逆。您试图通信的数据的域是什么?如果您想缩小一些,如果您没有任何安全要求,那么您谈论的是压缩。如果您想将压缩后的表单存储在特定的字符串中,那么您正在谈论编码。如果您不介意,我会相应地更改标记。base64本身实际上会增长字符串。我考虑的是base64,但随着字符串长度的增长,base64也会增长。我想可能还有另一种解决办法。@cmd-Hmm,没错;我想可以将字符串(似乎是数字和破折号)表示的数据转换为二进制,然后用base64编码,但这似乎是一个非常麻烦的问题。@MihaiZamfir您可以将一个表示放大到一个固定的极限,但不能将它缩小到一个固定的极限而不丢失数据。当然,有实际的压缩,但我不知道有多少压缩技术可以处理超小的字符串。值得一提的是,URL中晦涩难懂的查询字符串对于大多数主要网站来说都是事实。比如Youtube、亚马逊、谷歌……我不介意投反对票,但原因是什么?如何改进答案?我的猜测是,正如你提到的,当碰撞发生时,这不起作用。谁想依赖于某种可能不会破裂的东西,但当第一次碰撞真正发生时,解决方案就行不通了?@StephanRyer我可能低估了这种可能性在实践中有多低。在任何情况下,都可以很容易地检测到冲突,并根据特定任务提供解决方案。概率增加了需要加密的字符串的数量,因此,在不知道这个数字的情况下,实际上不可能对发生这种情况的总体可能性说任何话。@StephanRyer可能的sha256哈希数:
2**256
相比之下,以秒为单位的宇宙年龄很小:
~10**21
。在宇宙存在的每一秒,你可以每秒生成数十亿个哈希,并且你只使用所有可能哈希中的一小部分。考虑到解决方案使用了DB,如果我们检测到非常不可能的冲突(只需删除代码中的“或忽略”),我们可以在许多可能的候选对象中使用一个无随机哈希。
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=