需求是这样的,有个数据表,存放大量哈希值。
无论是 md5 还是 sha1 的长度都比较长,而且他们的取值范围都是 16 进制数( 0-9,a-f )
有没有什么广泛使用的算法,用( 0-9,a-z,A-Z )来表示他们,从而缩短他们的长度。
注:
-
之所以要这样缩短的主要原因是为了减少数据库空间占用;
-
这个算法最好是使用的比较广泛的,因为这个需求自己写一个程序映射应该也可以,但还是希望能找到一个更加广泛通用的解决方案;
-
这个算法要能互逆

需求是这样的,有个数据表,存放大量哈希值。
无论是 md5 还是 sha1 的长度都比较长,而且他们的取值范围都是 16 进制数( 0-9,a-f )
有没有什么广泛使用的算法,用( 0-9,a-z,A-Z )来表示他们,从而缩短他们的长度。
注:
之所以要这样缩短的主要原因是为了减少数据库空间占用;
这个算法最好是使用的比较广泛的,因为这个需求自己写一个程序映射应该也可以,但还是希望能找到一个更加广泛通用的解决方案;
这个算法要能互逆
1 also24 Nov 23, 2019 via Android 这个不需要算法,进制换算就够了 |
2 also24 Nov 23, 2019 via Android 或者这样说,你对 md5 的输出有误解 md5 输出的是 128bit,只是为了方便你看,才展示为 32 位 HEX String 你完全可以直接存储这 128bit 以达到最小化空间占用 |
3 NeinChn Nov 23, 2019 MD5/SHA1 能互逆? |
4 ipwx Nov 23, 2019 via Android 你可以用 binary type 存。但如果这你还不满足,那没有办法了 |
5 ipwx Nov 23, 2019 via Android 事实上每两位 hex 等于一位二进制八位 |
8 0TSH60F7J2rVkg8t Nov 23, 2019 via iPhone 把二进制 binary 用 base64 encode 一下就行了 |
11 also24 Nov 23, 2019 |
12 woodensail Nov 23, 2019 base64 了解一下,一个字节能存 6bit,24 个字符搞定 或者不要求可读性,直接存字节数组,16 个字节搞定 |
15 passerbytiny Nov 23, 2019 你经常看到的 Md5/SHA1/UUID 等,并不是 16 进制数据,他的标准叫法是十六进制转储 /Hex dump ( https://zh.wikipedia.org/wiki/%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%82%A8 )。本质上,是处于可视化的目的,将二进制数据以十六进制数据(字符串形式)打印出来。 虽然你看到的是十六进制,但存储的不一定是。如果存储原始数据,那么是二进制数据;如果存储你看到的十六进制字符串,那么仍然是二进制数据,只不过是经过转码后的二进制数据,长度是原始二进制数据的两倍。所以,你只需要把存储格式,从字符串格式,改成原始二进制格式,就会压缩一半的存储空间。 |
16 geelaw Nov 23, 2019 via iPhone int128 咯 |
17 passerbytiny Nov 23, 2019 @nyse #7 通用方法,也就 hex dump ( 16 → 32 )和 base64 encode ( 16 →24 )了,再短就要自创方法了。 |
18 also24 Nov 23, 2019 @hdbzsgm #10 对于楼主的语境来说是 原始数据是 128bit 楼主当前使用的方式( HEX string )是 32byte -> 256bit 而 128bit 数据在 base64 之后得到的字符串是 129/3*4 = 172 bit 172bit < 256bit,所以对于楼主来说,数据确实被 『压缩』了 |
20 also24 Nov 23, 2019 @hdbzsgm #10 修正一下计算方式,应该是 128 / 8 = 16byte ( 16 + 2 ) / 3 * 4 = 24byte 补两个 == 之后 24 + 2 = 26byte 26 * 8 = 208 bit 208bit < 256bit |
22 xmadi Nov 23, 2019 via iPhone 使用 36 进制(0-9,a-z,不区分大小写) 或者 base64 如果觉得 base64 的两个符号太麻烦 可以使用 base62 ( 0-9,a-z,A-Z ) 就是楼主想要的东西 |
23 imn1 Nov 23, 2019 难道是彩虹表? |
24 keepeye Nov 23, 2019 import string digs = string.digits + string.ascii_letters + '!@#$%^&*()_+:;<>,.?/[]{}' def int2base(x, base): if x < 0: sign = -1 elif x == 0: return digs[0] else: sign = 1 x *= sign digits = [] while x: digits.append(digs[int(x % base)]) x = int(x / base) if sign < 0: digits.append('-') digits.reverse() return ''.join(digits) def main(): src = b'test' e = hashlib.md5(src).digest() a1 = struct.unpack('q', a[0:8]) a2 = struct.unpack('q', a[8:]) print(int2base(a1[0], 86) + int2base(a2[0], 86)) # 最终输出 20 个字符 |
27 wlh233 Nov 24, 2019 @also24 https://tools.ietf.org/html/rfc3548#section-7 所以多算了啊,补齐之后没用上的零比特最后变成等号了,总字节数就是这么多了,不用再加了 |