资讯专栏INFORMATION COLUMN

混淆id的一种方法

zengdongbao / 1151人阅读

摘要:这一条是我加的,能搜到很多混淆的方法但它们可能要求在之内,比如对求一个,这是一个不错的方法但因为这个限制我没有采用它。

众所周知,在web应用的API中,总是会出现数据库item的id。比如GET /posts/1表示获取id为1的文章内容。这样做十分简洁,但存在被人爬数据的风险。比如我可以大致猜测或者试一下id的范围,1,2,3...10000这样迭代地爬数据。如果服务器不做访问限制,很轻易就能把所有数据就能爬下来。而且,这样的数字id也会暴露一些信息,比如id小的一般是更早创建的。

所以要对id进行混淆,混淆有这么几个特点:

它是一个无符号整数到字符串的一一对应的函数

双向的,混淆之后可以恢复,所以不能用hash

不表现出递增的特征

不用像加密那样强,也不用有密钥

没有整数范围的限制。这一条是我加的,google能搜到很多id混淆的方法但它们可能要求id在2^32-1之内,比如对2^32求一个multiplicative inverse,这是一个不错的方法但因为这个限制我没有采用它。

最简单的一个方法是找一个比较大的数字进行异或,比如1-10跟1093420374进行异或的结果是这样的:

1 : 1093420375
2 : 1093420372
3 : 1093420373
4 : 1093420370
5 : 1093420371
6 : 1093420368
7 : 1093420369
8 : 1093420382
9 : 1093420383
10: 1093420380

但这比较容易被人猜出是异或,需要再加上别的操作

我看到的一个比较好的方法也是我目前在用的是:

对id求个hash,取前16字节,作为segment1

对segment1求hash,取前8字节,作为segment2

将segment2转换为整数,加上id,再变回byte array

将segment1和segment2连接起来再求个hash,取前8字节,作为segment3(用于恢复时的验证)

连接segment1、2、3,做base64,得到混淆后的id

恢复的时候只用

base64解码

取前16字节得到segment1,后8字节得到segment3,剩余字节是segment2

验证hash(segmemt1+segment2)是否等于segment3

int(segment2)-int(hash(segment1))得到id

这用python实现比较方便,因为python的整数可以无限大,代码是这样的

pythonclass Obfuscator:
    _head_bytes = 16
    _mid_bytes = 8
    _tail_bytes = 8

    @staticmethod
    def bytearray_to_int(byte_arr):
        return int.from_bytes(byte_arr, byteorder="big")

    @staticmethod
    def int_to_bytearray(num):
        assert isinstance(num, int) and num >= 0
        if num == 0:
            return b"0"
        result = []
        while num > 0:
            d, m = divmod(num, 256)
            result.append(m)
            num = d
        return bytes(result[::-1])

    @classmethod
    def obfuscate(cls, uid):
        if not uid:
            return ""
        uid_bytes = cls.int_to_bytearray(uid)
        seg1 = hashlib.sha1(uid_bytes).digest()[:cls._head_bytes]

        seg2 = hashlib.sha1(seg1).digest()[:cls._mid_bytes]
        seg2 = cls.int_to_bytearray(uid + cls.bytearray_to_int(seg2))

        seg3 = hashlib.sha1(seg1 + seg2).digest()[:cls._tail_bytes]

        return base64.urlsafe_b64encode(seg1 + seg2 + seg3).decode()

    @classmethod
    def restore(cls, obscure_str):
        if not obscure_str:
            return -1
        seg_bytes = base64.urlsafe_b64decode(obscure_str)
        seg1 = seg_bytes[:cls._head_bytes]
        seg2 = seg_bytes[cls._head_bytes:-cls._tail_bytes]
        seg3 = seg_bytes[-cls._tail_bytes:]

        if hashlib.sha1(seg1 + seg2).digest()[:cls._tail_bytes] != seg3:
            return -1
        seg1 = hashlib.sha1(seg1).digest()[:cls._mid_bytes]
        return cls.bytearray_to_int(seg2) - cls.bytearray_to_int(seg1)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45367.html

相关文章

  • web安全三,XSS攻击

    摘要:我把这个领域的东西写成了一个系列,以后还会继续完善下去安全一同源策略与跨域安全二攻击安全三攻击 上文说完了CSRF攻击,本文继续研究它的兄弟XSS攻击。 什么是XSS攻击 XSS攻击全名(Cross-Site-Script)跨域脚本攻击,为了跟CSS(Cascading-Style-Sheet)区分开来,所以缩写是XSS。 XSS攻击的原理 上一节说道的CSRF攻击是利用的是伪请求,这...

    jlanglang 评论0 收藏0
  • web安全三,XSS攻击

    摘要:我把这个领域的东西写成了一个系列,以后还会继续完善下去安全一同源策略与跨域安全二攻击安全三攻击 上文说完了CSRF攻击,本文继续研究它的兄弟XSS攻击。 什么是XSS攻击 XSS攻击全名(Cross-Site-Script)跨域脚本攻击,为了跟CSS(Cascading-Style-Sheet)区分开来,所以缩写是XSS。 XSS攻击的原理 上一节说道的CSRF攻击是利用的是伪请求,这...

    JiaXinYi 评论0 收藏0
  • 微信Android资源混淆打包工具,如何让应用安装包立减1M

    摘要:腾讯特约作者微信客户端高级工程师微信中的资源混淆工具主要为了混淆资源长度例如将混淆为,同时利用深度压缩,大大减少了安装包体积,同时也增加了逼格,提升了反破解难度。写在前言资源混淆工具大约是在年月实现,并在微信中使用,减少了大约的空间。 腾讯Bugly特约作者: 微信客户端高级工程师 shwen 微信中的资源混淆工具主要为了混淆资源ID长度(例如将res/drawable/welcome...

    Honwhy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<